操作必有反馈
点完之后,用户怎么知道生效了。
用户点了一下,屏幕上必须有东西变化。没有变化,他的默认假设是没点上。这个原则从唐纳德·诺曼的《设计心理学》就讲起:一个操作发生后,系统必须在合理时间内给出可见的回应,否则用户无法把「我做了什么」和「发生了什么」连起来。norman-wiki
你会遇到的现象:
- 用户连点三次提交,后台收到三条重复数据
- 点了之后过两秒才有反应,中间那两秒他以为坏了
- 操作成功了,但页面上看不出哪里变了
三层反馈
一次操作要配齐三层反馈,每层回答一个不同的问题:
| 层 | 什么时候出现 | 它回答的问题 |
|---|---|---|
| 即时反馈 | 手指抬起的瞬间 | 我点上了吗。按钮变色、变成加载态、涟漪效果 |
| 结果反馈 | 操作完成时 | 成功了还是失败了。轻提示、状态标签、错误信息 |
| 状态反馈 | 操作完成之后一直存在 | 现在是什么状态。列表里的数据真的变了、标记变了 |
第三层最容易被漏。弹了个「保存成功」但列表还是旧数据,用户会怀疑到底存没存上,然后刷新一遍页面确认。
三层不是可选项。即时反馈管「点没点上」,结果反馈管「成没成」,状态反馈管「现在什么样」——一层的缺位都会让用户去做本不该做的动作:连点三次提交、刷新页面确认、翻到别的页面看数据变没变。你省掉的每一层,都变成了用户多做的动作。
按耗时选形式
反馈在什么时候给,按耗时分档:
- 小于 0.1 秒,不显示加载态,直接出结果。
- 0.1 到 1 秒,局部加载态,按钮内转圈就够了,别遮罩整页。
- 超过 1 秒,用骨架屏或进度条。不确定要多久的操作,进度条至少要会动——一个卡住不动的进度条比没有进度条更让人焦虑。
- 超过 10 秒,允许后台运行,给出可以离开的入口,别让用户干等。
这条分档也解释了为什么「加载中」不能随手写。一个 0.3 秒就完成的保存,如果硬塞一个转圈动画,反而让用户觉得慢。反馈的时机本身也是一种设计,不是顺手加的装饰。
乐观更新
有一类操作可以不等服务器:点赞、收藏、勾选待办。界面先按成功处理,请求失败了再退回来并提示。
- **适合用的:轻量、高频、失败了退回来代价很小的操作。**点赞点错了退回去,用户不会有损失。
- **不适合用的:涉及钱、不可逆、或者结果需要服务端计算的操作。**下单、支付、删除,都要等真实结果。
- **失败时必须退回并说明。**悄悄退回去比不做乐观更新更糟——用户以为成功了,过一会儿发现没有。
还有一个判断值得记住:乐观更新解决的是「延迟」问题,不是「失败」问题。如果这个操作经常失败,先解决失败率,再谈要不要乐观——在一个本来就不稳定的接口上做乐观更新,等于把不确定性加倍转嫁给用户。
给 AI 的话
把这段写进项目的 CLAUDE.md:
## 操作反馈
任何会触发请求的操作,都要实现三层反馈:
1. 即时:点击瞬间按钮进入 loading 态并禁用,防止重复提交。
2. 结果:成功或失败都要有明确提示。失败的提示要包含
原因和下一步(见提示语规范)。
3. 状态:操作完成后,页面上相关的数据必须同步更新,
不能只弹提示不刷新列表。
按耗时选形式:
- < 0.1s 不显示加载态
- 0.1~1s 局部加载态(按钮内),不要遮罩整页
- > 1s 骨架屏或进度条
- > 10s 允许后台运行,给出可离开的入口
乐观更新只用于点赞、收藏、勾选这类轻操作,
且失败时必须回滚并提示。涉及金额、删除、
不可逆的操作一律等待服务端结果。
这段提示词把「三层反馈」从口头要求变成了每次生成代码的默认规则,特别是「不能只弹提示不刷新列表」这一句,专治那种看上去成功、实际上没存上的假反馈。
