做产品 PMaker
空格的键盘
只写了正常态
四态齐全
切换后端返回的情况:

同一个列表组件,左边是让 AI 直接写出来的版本,右边补齐了四种状态。点上面的按钮切换。

Cover All Four States

A piece of interface shows four faces in the real world, and the AI usually builds only one of them. The other three are either blank or shove the error straight at the user.

What you will run into
  • 自己演示一切正常,同事一登录就是白屏,因为他账号里没数据
  • 网慢的时候页面先塌下去,数据回来又撑开,正要点的按钮跑掉了
  • 接口一挂整页变成 Uncaught TypeError,用户只能刷新碰运气

The cause isn't the model. You say "build an order list" and the picture in its head is a screen of neatly arranged orders, because that's all your description contains. Empty, loading, and error never appear in the spec — they only appear on real users' hands: a brand-new sign-up opening it for the first time, the signal dropping on the subway, the backend happening to be mid-deploy.

Filling them in usually costs a few dozen lines of code. The real hurdle is treating them as part of the spec when you write it, not patching them in after the bug reports arrive.

How to Tell

Any time you fetch data, the result lands in one of four cells. Walk through this diagram and you'll know which one you missed.

发起请求 还没回来 失败了 成功,但没数据 成功,有数据 加载态 错误态 空态 正常态 还要多久,页面会不会跳 怎么回事,我能做什么 为什么是空的, 下一步该干什么 最重要的那条看得到吗
The intensity tiers draw on common practice in hint design. The test is simple: if the user doesn't handle this, does something go wrong.

Design Considerations

What form the hint takes depends on how serious the matter is. Three tiers from strong to weak — skipping a tier means the user quickly learns to click "OK" with their eyes closed.

弹窗 · 强 必须立刻处理的错误 全局横幅 · 中 状态变化,不必立刻行动 气泡 · 弱 可看可不看的信息
The intensity tiers draw on common practice in hint design. The test is simple: if the user doesn't handle this, does something go wrong.

Note for the AI

Put it in the component spec, or sink it into the project's CLAUDE.md, and every data component generated from then on will carry all four states by default.

PROMPT · Component need
凡是涉及异步数据的组件,必须同时实现四种状态,缺一不可:

1. 正常态:有数据时的正常渲染。
2. 空态:数据为空数组时。区分两种来源——
   - 用户还没有任何数据:给一句说明 + 一个主行动按钮
   - 筛选/搜索后无结果:提示放宽条件 + 一键清除筛选
3. 加载态:使用骨架屏,形状和数量贴近真实内容,不要用居中 spinner。
4. 错误态:按「说明当前状况 + 引导措施」写文案,配一个「重试」按钮,
   不要暴露状态码或堆栈。

文案规范:
- 不使用感叹号;句尾除疑问句外不加标点。
- 等待类文案统一以「…」结尾,例如「加载中…」。
- 提示强度分三档:必须立刻处理用弹窗,状态变化用全局横幅,
  可看可不看用气泡。不要越级。

其他约束:
- 四种状态复用同一个外层容器,设置 min-height 避免切换时页面跳动。
- 错误只影响当前组件,不要向上冒泡导致整页变成错误页。
- 把状态做成组件的一个 prop('ok' | 'empty' | 'loading' | 'error'),
  这样我可以在不改后端的情况下逐个预览。

先告诉我这四种状态分别打算怎么呈现,我确认后你再写代码。

That last line is critical. Asking it to describe the approach first lets you tell in seconds whether the empty state is yet another four-character "no data yet" — far faster than reading the code and redoing it.

Real Examples

还没有任何笔记

What you write shows up here, ready to search and organize at any time.

新建第一篇

Notion's empty database offers a few template options and a creation entry — using that space to teach the user what to do next.

Linear's loading skeleton reproduces the real content's row height and columns, so when the data arrives the switch is almost imperceptible and the page doesn't jump.