空状态应使用语义化的 包裹,作为列表直接子元素,添加 aria-live="polite" 和 role="alert";通过 .list.empty > li 隐藏真实项、.list.empty > li.empty-state 显示提示;逻辑须内置于列表组件,判断 data.length === 0 && !loading && !error;不可外置为独立组件,以保障可访问性、样式继承与键盘导航流。

空状态提示该用什么 HTML 结构
空状态不是随便放个 <div> 或 <code><p></p> 就完事。语义上它属于列表的“内容缺失反馈”,应作为列表容器的直接子元素,且需兼顾可访问性。最稳妥的方式是把提示包裹在 <li> 里,和真实数据项同级,并添加 aria-live="polite" 和 role="alert"(仅当为空时动态插入)。
不要用 <h2></h2> 或 <section></section> 单独包裹空提示——它不属于页面大纲层级,只是列表内部的状态反馈。也不建议用伪元素(::before)生成文字,屏幕阅读器无法读取,且无法聚焦或翻译。
如何让空状态在 CSS 中自动显示/隐藏
核心原则:不靠 JS 控制 display,而是用 class 切换 + CSS 选择器联动。给列表容器加一个 empty 类,再用 .list.empty > li 隐藏所有真实项,同时用 .list.empty > li.empty-state 显式显示空提示项。
- 避免写
display: none在空提示元素本身上——这样 JS 切换 class 时容易漏掉过渡或动画逻辑 - 推荐用
opacity: 0; height: 0; overflow: hidden;配合transition实现淡入淡出,比单纯display更可控 - 如果列表用
flex或grid布局,注意空状态<li>也要继承相同align-items和justify-content,否则垂直居中会失效
React/Vue 场景下空状态的渲染边界在哪
空状态逻辑必须收束在列表组件内部,而不是由父组件传入一个“空提示 JSX”。否则容易导致:父组件忘记传、提示文案与业务语境脱节、加载态和空态混淆(比如接口返回 [] 但还在 loading,此时不该显示空提示)。
- 在列表组件内判断
data.length === 0 && !loading && !error是唯一安全的空态触发条件 - Vue 用户慎用
v-if直接切整个<li>——可能破坏key复用逻辑;推荐统一用v-show或 class 控制显隐 - React 中若用
useMemo缓存空提示节点,请确保依赖数组包含data、loading、error全部三项,缺一不可
为什么不能把空状态做成独立组件嵌套在列表外
看似解耦,实则破坏 DOM 层级关系和键盘导航流。用户按 Tab 键从列表标题跳到列表内容时,焦点会直接跳过空提示,因为它不在 <ul></ul> 内部;SR(屏幕阅读器)也会把它识别为独立段落,而非列表的上下文补充。
更严重的是样式继承断裂:font-size、line-height、color 等往往依赖列表父级设置,外置后需重复声明,维护成本陡增。真正的解耦方式是抽离空提示的文案和图标配置项,而不是 DOM 结构。











