G4.01.3restore state after back设计研究

返回后应恢复原页面的状态

别名: 返回恢复状态 · state restoration · bfcache · 回退保活

概念解释

点返回不是重新打开一页,而是回到刚才离开的那一帧state restoration(状态恢复)在这里的最低要求是:那一帧看起来还是离开时的样子——还在刚才的位置、还认得出刚才在做什么——而不是一次全新的首屏加载。浏览器的后退-前进缓存(bfcache)和原生 back stack 里未销毁的页面,默认就是这个承诺。产品若在返回时把页面当新访问重跑,等于把「撤销上一次前进」做成了「另开一张同类页」。

这条只立原则:返回应交出原帧,而不是一张重置页。滚动到哪一条、筛选是否还在、列表在离开期间变了该按对象还是按像素对齐,是更细的保持问题,不在这里展开。

机制

返回被当作时间撤销,人的工作记忆里还挂着离开前的视觉快照:列表停在哪一带、表单填到哪、哪一张卡片正打开。快照对不上,撤销就失败——人会怀疑走错了页,或以为系统把工作清掉了。失败通常来自三处:路由把返回做成一次新的 fetch+首屏;单页应用卸载了上一个视图,回来只重建初始 state;移动端为省内存杀掉了上一个 activity,重建时没有把实例状态写回来。

SPA 特别容易踩。前进时把列表组件销毁,返回时 useEffect 按默认参数再请求第一页,视觉上就是「被扔回顶部」。原生侧 onCreate 当新开、不读 savedInstanceState,效果相同。用户无法区分「这是返回」和「这是新打开」,因为两者的第一帧被做成了一模一样。

怎么研究

离开-返回配对:在列表或表单上制造可观察的状态(滚过一屏、勾选一项、打开一块面板),进入下一页再返回,判定状态是否仍在。

  • 自变量:实现(bfcache 命中 / 普通重载 / SPA 销毁重建 / 进程被杀后重建)、离开时长。
  • 因变量:返回后与离开前的可观察差异、被试是否把返回描述成「新打开」、补做刚才操作的次数。
  • 方法论注意点:只测「有没有回到同一 URL」会漏掉整类失败——URL 对了,state 是初始值。必须在离开前做一次不可从 URL 读出的操作(滚动、未提交勾选)。实验室里秒回会高估 bfcache;加上切到其他 App 几十秒再回来,才看得到被系统回收的那条路径。

边界

用户在下一页完成了会让上一页过时的动作(删除了刚看的那一项、提交了表单、退出登录),原帧不该原样冻住,否则恢复的是一份已经作废的世界。支付、选座这类有服务端锁定期的页,返回时锁可能已释放,恢复外观但功能已变,需要的是重新校验而不是盲信本地快照。只读内容在离开期间被编辑器更新,原帧是过期副本,这条的「应恢复」让位于新鲜度。

怎么落地

  • 把返回实现成恢复已有实例或命中 bfcache,而不是导航到同一路径的一次新打开。SPA 对返回栈上的视图保留组件状态,不要在每次 pageshow 里按默认参数重拉。
  • 进程可能被杀时,离开前把最小实例状态(当前路由、关键 UI 开闭)写入可恢复存储,重建后读回来;不要只靠内存里的 Vue/React state。
  • 返回落地的第一帧禁止先闪默认首屏再跳回,那会被读成重置。
  • 验证:在列表上滚过一屏并展开一行,进详情,返回。展开仍在,位置仍在,不准出现顶部闪一下。再在中途把 App 送进后台直到可能被回收,冷启动走返回栈,同一条仍要成立。

延伸

  • 同组G4.01.1 返回上一页与返回上一级是两种语义 · G4.01.2 跨来源进入时返回的目标不确定
  • 相邻G4.03 状态保持 · G4.07 状态保持与位置恢复 · I3.06 状态持久化
  • 站内检索state restoration · bfcache · back stack

同组卡片

快捷操作

分享

分享当前页面

ios_share

https://hci.top/zh/handbook/G4.01.3