页面运行时状态
页面运行时状态指当前文档对应的 JS 内存、DOM 树和临时 UI 现场;整页导航或刷新时它通常会被销毁。
#type / concept
#status / growing
#tech / dev / frontend
#platform / browser
#resource / web
[!info] related notes
- 所属 MOC: 前端基础 MOC, javascript-in-browser-moc
- 上位主题: javascript-in-browser
- 前置概念: 路由, 浏览器客户端存储
- 并列概念: BFCache 页面级缓存
- 关系笔记: 浏览器导航与前端路由
页面运行时状态
页面运行时状态指的是:当前文档这一次运行过程中,实际活在页面环境里的那份状态现场。
一句话定义
它主要包括当前页面的 JS 堆内存、组件树状态、DOM 树状态以及各种尚未持久化的临时 UI 状态。
为什么这个概念重要
很多人说“整页跳转会丢状态”,真正容易丢的通常不是 sessionStorage 或数据库里的数据,而是这份只存在于当前页面运行现场里的状态。
它通常包含什么
JS 内存状态
- React / Vue 组件 state
- 全局 store 里的内存数据
- 普通变量、闭包里的中间值
- 已请求回来但尚未持久化的数据缓存
DOM 状态
- 输入框里尚未提交的内容
- 当前滚动位置
- 节点展开 / 折叠状态
- 焦点位置
- 动画中间态
临时 UI 状态
- 当前打开了哪个弹窗
- 当前选中了哪个 tab
- 当前列表展开到哪一层
- 当前页面是否处于某个加载中的过渡状态
它不等于什么
不等于 Web Storage
sessionStoragelocalStorage
这些属于浏览器提供的持久化或半持久化存储,不等于当前页面运行现场本身。见 浏览器客户端存储。
不等于服务端状态
- 用户资料
- 已保存草稿
- 服务端购物车
- 数据库记录
这些状态不随着当前页面 JS 上下文销毁而一起消失。
为什么整页跳转或刷新时它会丢
传统整页导航时,浏览器通常会:
- 卸载当前文档
- 销毁当前页面对应的 JS 执行环境
- 销毁旧 DOM 树
- 加载新的 HTML
- 创建新的页面环境
所以只要状态没有被同步到 URL、Storage、服务端或其他持久层,它就会随着旧页面一起消失。
和 sessionStorage 最容易混淆的点
sessionStorage 通常在同一个 tab 的会话期内还能保留,但页面运行时状态不会自动写进去。
也就是说:
sessionStorage能保住“一个值”- 但它保不住“当前页面已经运行到哪一步”
例如它可以保住:
draft = "hello"
但它保不住:
- 某个 Promise 正执行到哪
- 某个组件树当前已经挂载到什么状态
- 某个动画中间帧
- 某些闭包现场
为什么 SPA 更容易保住它
SPA 路由切换时,通常不会销毁整个文档和 JS 运行环境,而是:
- 更新 URL
- 切换部分组件
- 复用全局 store、缓存和布局
所以很多状态仍然活在同一个应用运行时里。
但这不代表 SPA 天然不会丢状态。只要用户刷新页面,或状态只存在某个已卸载组件里,它仍然可能丢失。
前进后退是一个特例
如果浏览器命中 BFCache 页面级缓存,前进后退有时会直接恢复整个页面快照,而不是重新初始化页面。
这时用户会感觉“状态没丢”,因为浏览器恢复的正是之前那份页面运行现场。
最短记忆方式
页面运行时状态 = 当前页面这一次运行里活着的 JS 内存 + DOM 状态 + 临时 UI 现场。