空状态文案需满足四点:数据为[]时自然浮现、读屏器准确传达、不闪屏、区分“没数据”与“加载失败”;应使用语义化HTML元素包裹,如<ul>或<section role="region">,并添加aria-live、tabindex="-1"等属性确保可访问性。

空状态文案不是“写一句提示”就完事,它得在数据为 [] 时自然浮现、被读屏器准确传达、不触发闪屏、且能区分“没数据”和“加载失败”——这四点没对齐,文案再暖心也白搭。
空状态文案该用什么 HTML 元素包裹
别用裸 <div> 包文案。它没有语义,屏幕阅读器可能跳过,SEO 也不认。关键看它所处的上下文:
- 如果是列表(
<ul>或<ol>)的 fallback,直接用<ul aria-live="polite"><li>暂无数据</li></ul>—— 复用容器语义,hydration 时无需额外判断显隐 - 如果是卡片流或自定义区域,至少用
<section role="region" aria-labelledby="empty-title">,并配一个带id="empty-title"的<h3>标题 - 绝对避免:
<div class="empty">暂无内容</div>—— 没role、没aria-live、没焦点能力,等于对视障用户隐身
如何让空状态文案真正被用户“感知到”
视觉上显示 ≠ 用户已知状态变更。尤其 JS 动态插入空状态时,必须主动“喊一嗓子”:
- 给文案容器加
aria-live="polite",确保读屏器能捕获插入动作 - 插入后立即调用
element.focus(),但前提是该元素有tabindex="-1" - 文案本身要明确意图:用“暂无符合筛选条件的数据”而非“没有结果”,用“网络连接失败”而非“加载出错了”
- 别只靠颜色区分状态——灰色“暂无数据”和红色“加载失败”在色觉障碍下几乎一样,必须搭配图标 + 文字双重表达
React/Vue 中渲染空状态文案的常见翻车点
框架里最容易因“falsy 判断”漏掉空状态,导致页面一片空白:
立即学习“前端免费学习笔记(深入)”;
- React 中写
{list.map(...)} || '暂无数据'是错的 ——[].map()返回空数组[],而[] || 'xxx'还是[],根本不会渲染文案 - 正确写法:
{list.length === 0 ? <code>NoData /> : list.map(...)} - Vue 中用
v-if="list.length"包整个<ul>,v-else放空提示,且两者必须同级、不能共存于一个父节点内 - SSR 场景下,服务端已输出空状态 DOM,但客户端 hydration 后数据秒到,会造成“闪一下空状态又消失”——解决办法是让客户端统一接管判定逻辑,服务端只输出骨架,不预判空/非空
空状态文案必须区分的两种底层原因
用户看到“暂无数据”,心里想的是“是我操作错了?还是系统坏了?”,文案要立刻回答这个问题:
- 接口返回 200 + data: [] → 属于业务正常流,文案应引导下一步操作:“暂无符合当前筛选条件的数据,试试清空筛选?”
- fetch 抛错 / response.status !== 200 → 属于异常流,文案需降低预期+提供重试:“加载失败,请检查网络后点击重试”,按钮绑定真实重试函数,而非刷新页面
- 永远不要把
error.message直接塞进文案,比如"TypeError: Failed to fetch"—— 这不是用户语言,要映射成可理解、可操作的提示
最常被忽略的一点:空状态文案不是设计稿里的静态文案,它是数据流终点的“最后一句人话”。它得经得起 SSR/hydrate 冲突、读屏器逐字朗读、以及用户手指误点重试按钮三次后的耐心考验。



















