Snackbar & Undo:用「可以反悔」替代「你确定吗」
要删除一封邮件,常见做法是先弹一个 confirm:「确定删除吗?」——可几乎没人会回答「不」,这个对话框打断了每一次操作,只为防住极少数的误删。Gmail 的思路相反:直接执行,再从底部滑出一条带「撤销」的
Snackbar,几秒内不点就永久生效。它把确认成本从「每次操作前」挪到了「真的想反悔时」。下面交互对比两种流程。
Snackbar 的几个细节都能在上面观察到:倒计时进度条给出剩余的反悔时间;悬停暂停 (animation-play-state: paused) 让正想点撤销的用户有充裕时间完成操作;同时删多条时 Snackbar
垂直排队而非互相覆盖。真正的「删除」只在倒计时自然走完时才提交给后端——在此之前数据只是视觉上移除,撤销零成本。
删除即软删除,提交推迟到倒计时结束——撤销 = 取消那个 timer:
function remove(item) {
const i = list.indexOf(item);
list.splice(i, 1); // 1. 立即软删除 (仅前端)
render();
const timer = setTimeout(() => {
api.delete(item.id); // 3a. 倒计时走完才真正提交
}, UNDO_WINDOW);
showSnackbar('已删除', () => {
clearTimeout(timer); // 3b. 撤销 = 取消提交
list.splice(i, 0, item); // 放回原位
render();
});
}
| 维度 | confirm 确认框 | Snackbar + 撤销 |
|---|---|---|
| 打断时机 | 每次操作前 | 仅在想反悔时事后 |
| 常规路径成本 | 多一次点击 | 零额外点击 |
| 线程 | 阻塞 (原生) | 非阻塞 |
| 误操作可挽回 | 提交前可取消 | 提交后短时间内仍可撤销 |
| 适用 | 不可逆 / 高危 (清空账户) | 可逆的高频操作 (删邮件 / 归档) |
Snackbar 不是万能替代品:对真正不可逆的操作(永久销毁、付款),仍应保留显式确认。它和 Optimistic UI 同源——都信任「操作通常没问题」,把代价推迟到例外发生时。Material Design 把它规范为 Snackbar,iOS 上的对应物则是顶部的 banner + 撤销手势。