必须防抖预存而非依赖beforeunload保存,因后者仅50ms同步窗口且禁异步,localStorage.setItem()易写入旧值;可靠方案是input事件监听+600ms防抖+非空校验+上下文键名。

页面关闭前无法“实时保存”动态内容,必须靠 beforeunload + 手动脏标记 + 防抖预存组合实现;现代浏览器已屏蔽自定义提示文字,且不允许在 beforeunload 中执行异步操作。
为什么不能在 beforeunload 里调用 localStorage.setItem()?
很多人误以为 beforeunload 是个“最后抢救机会”,试图在里面写入数据。但实际它只给浏览器约 50ms 同步执行窗口,localStorage.setItem() 虽是同步 API,但若此前没做过防抖预存,用户刚敲完字就关页,此时 DOM 还没来得及更新、值也未序列化,setItem() 写的仍是旧内容或空值。
-
beforeunload回调中禁止await、fetch、setTimeout等任何异步行为,否则直接忽略 - 移动端(尤其 Safari iOS)对
beforeunload支持极弱,键盘收起、切后台时大概率不触发 - Chrome/Firefox 已强制统一提示文案,
e.returnValue = "xxx"或return "xxx"全部失效,只显示“离开此页面?您输入的数据可能未保存。”
真正可靠的保存时机:防抖 + input 事件监听
所有动态内容(、、)必须在用户停顿后立刻存入 localStorage,而不是等关页才动。这是唯一能覆盖“关页前最后一秒输入”的做法。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 用
input事件而非change或blur:它捕获按键、粘贴、中文上屏全过程,响应更及时 - 手写防抖(不用 Lodash),延迟设为
600ms:太短(如 200ms)易漏中文输入法组合过程;太长(如 1500ms)易丢临界输入 - 只存非空字段:
if (el.value.trim()) { ... },避免覆盖 placeholder 或初始值 - 键名带上下文:
draft-${location.pathname}-${form.id},防止多表单互相覆盖 - 存前必须
JSON.stringify(),取回必须JSON.parse(),否则getItem()返回null会抛SyntaxError: Unexpected token u
beforeunload 的唯一合法用途:布尔判断 + 提示拦截
它不该干活,只该“喊一嗓子”。真正的保存动作必须提前完成,beforeunload 只负责检查“有没有还没存的改动”。
- 定义全局标志:
let hasUnsavedChanges = false - 每次
input触发时设为true;每次防抖存完后设为false -
beforeunload中只写:if (hasUnsavedChanges) return ''(返回空字符串即可激活系统提示) - 提交成功后务必重置:
hasUnsavedChanges = false,否则用户填完再关页仍被拦 - Safari 在 iframe 或某些 PWA 场景下会静默忽略
beforeunload,需额外监听visibilitychange做补漏
容易被忽略的兼容性陷阱
看似简单的草稿保存,实际在 Safari 无痕模式、低配安卓机、富文本编辑器中极易失效。
- Safari 无痕模式下
localStorage直接静默失败,try/catch捕获不到异常,需先做可用性探测:try { localStorage.setItem('test', '1'); localStorage.removeItem('test'); } catch(e) { /* fallback */ } - 富文本编辑器(如 Quill、Tiptap)不触发原生
input事件,得监听其专用事件,如text-change或update - 中文输入法场景下,
input在选词过程中高频触发,若没防抖+空值过滤,会导致localStorage被脏数据反复覆盖 - 页面加载恢复草稿后,必须手动触发
dispatchEvent(new Event('input', { bubbles: true })),否则 Vue/React 等框架无法感知值变更
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










