四态齐全
一块界面在真实环境里会出现四种样子,AI 通常只做出其中一种。剩下三种要么一片空白,要么直接把报错摊在用户面前。
你会遇到的现象
- 自己演示一切正常,同事一登录就是白屏,因为他账号里没数据
- 网慢的时候页面先塌下去,数据回来又撑开,正要点的按钮跑掉了
- 接口一挂整页变成 Uncaught TypeError,用户只能刷新碰运气
原因不在模型。你说做一个订单列表,它脑子里的画面就是一屏排列整齐的订单,因为你给它的描述里也只有这一种。空、加载、出错这三种情况在需求文档里从来不出现,只在真实用户手上出现:新注册的人第一次打开、地铁里信号断了、后端刚好在发版。
补齐的成本通常是几十行代码。真正的门槛是在写需求的时候就把它们当成需求的一部分,而不是等 bug 报上来再补。
怎么判断
任何一次取数据,结果只会落在四个格子里。照着这张图问一遍,就知道少写了哪个。
设计考量
- 空态是介绍产品的机会,别只写暂无数据。 用户第一次进来看到的多半就是空态。这块地方应该说清楚这里将来会有什么、以及怎么让它有,一句解释加一个主按钮。四个字的暂无数据把最好的教学位置浪费掉了。
- 加载用骨架屏,别用居中转圈。 骨架屏提前占住内容将来的位置,数据到达时页面不跳动;转圈会让整块区域先塌再撑开。超过一秒的等待才需要显示加载态,更短的反而闪一下更难受。
- 错误文案按「说明当前状况 + 引导措施」写。 先讲发生了什么(没连上服务器),再讲他能做什么(重试或检查网络)。这个公式套在任何一条提示上都成立。重试按钮放在文案旁边,别让人去刷新整页。
提示用什么形式,取决于这件事严不严重。三档从强到弱,越级使用的代价是用户很快学会闭眼点确定。
- 局部失败就局部提示,别让整页塌掉。 侧边栏的推荐模块挂了,不该导致整个页面变成错误页。状态的粒度要跟数据源的粒度对齐,每个独立请求各自管好自己那块区域。
- 四种状态的容器高度尽量接近。 切换时高度剧烈变化会导致页面跳动,用户正要点的按钮会跑掉。给容器一个 min-height,是成本最低的体验改善。
- 错误文案里不要用感叹号,句尾也不加标点。 感叹号会把一次网络波动渲染成事故。等待类文案统一用省略号收尾(加载中…),这是中文界面里比较通行的写法。
给 AI 的话
放进组件需求,或者直接沉淀到项目的 CLAUDE.md,之后每次生成数据组件都会默认带上四态。
PROMPT · 组件需求
凡是涉及异步数据的组件,必须同时实现四种状态,缺一不可: 1. 正常态:有数据时的正常渲染。 2. 空态:数据为空数组时。区分两种来源—— - 用户还没有任何数据:给一句说明 + 一个主行动按钮 - 筛选/搜索后无结果:提示放宽条件 + 一键清除筛选 3. 加载态:使用骨架屏,形状和数量贴近真实内容,不要用居中 spinner。 4. 错误态:按「说明当前状况 + 引导措施」写文案,配一个「重试」按钮, 不要暴露状态码或堆栈。 文案规范: - 不使用感叹号;句尾除疑问句外不加标点。 - 等待类文案统一以「…」结尾,例如「加载中…」。 - 提示强度分三档:必须立刻处理用弹窗,状态变化用全局横幅, 可看可不看用气泡。不要越级。 其他约束: - 四种状态复用同一个外层容器,设置 min-height 避免切换时页面跳动。 - 错误只影响当前组件,不要向上冒泡导致整页变成错误页。 - 把状态做成组件的一个 prop('ok' | 'empty' | 'loading' | 'error'), 这样我可以在不改后端的情况下逐个预览。 先告诉我这四种状态分别打算怎么呈现,我确认后你再写代码。
最后一句很关键。让它先描述方案,你能在几秒内看出空态是不是又写成了四个字的暂无数据,比读完代码再返工快得多。
相关模式
真实案例
还没有任何笔记
你写的东西会出现在这里,随时可以搜索和整理。
新建第一篇Notion 的空数据库会给出几个模板选项和一个创建入口,用这块地方教用户接下来做什么。
Linear 的加载骨架复刻了真实内容的行高和分栏,数据到达时几乎察觉不到切换,页面不发生跳动。
