防抖保存草稿需满足内容比对、上下文隔离、动态键名、800ms延迟触发、时间戳记录及dom就绪后恢复;避免拼音碎片、覆盖误存与丢稿。

用 <textarea></textarea> 做长文本编辑时,直接监听 input 并立刻存 localStorage 会存进拼音碎片、卡顿页面、覆盖有效草稿——防抖不是“加个延时”,而是让保存动作真正匹配人的输入节奏。
防抖必须带内容比对和上下文隔离
用户打“你好”,删掉重输“你好”,值没变,就不该再写一次。否则既浪费存储,又可能把中间态(如“ni”)误存为草稿。
- 每次输入前记录上一次已保存值:
let lastSavedValue = textarea.value - 防抖回调里先严格比对:
if (textarea.value !== lastSavedValue && textarea.value.trim() !== ''),满足才执行保存 - 键名不能写死为
"draft",要带页面路径和编辑器标识,例如:`draft-${location.pathname}-${textarea.id || 'main'}`,避免多个编辑页互相覆盖
保存时机选 800ms 防抖,不是定时轮询
用 setInterval 每 30 秒存一次,关页前最后一段文字大概率丢;而防抖在用户停笔后自然触发,更符合真实行为。
- 手写
setTimeout + clearTimeout,延迟设为 800ms(适配中文输入法完整选词节奏) - 每次新输入立即清除上一个定时器,确保只响应最后一次停顿
- 存入时附时间戳:
{ content: textarea.value, savedAt: Date.now() },为后续恢复校验提供依据
恢复草稿必须等 DOM 就绪并补发事件
脚本一加载就去读 localStorage 并赋值,常因 DOM 还没渲染或框架尚未初始化而失败——填了等于没填。
- 必须等
DOMContentLoaded触发后再执行恢复逻辑;Vue/React 项目则放在mounted或useEffect(() => {}, [])中 - 恢复前校验:
if (draft && draft.content && Date.now() - draft.savedAt ,只取 24 小时内有效草稿 - 赋值后手动派发事件:
textarea.dispatchEvent(new Event('input', { bubbles: true })),否则 Vue 的v-model、React 受控组件不会更新状态
敏感操作要兜底,但不能依赖 beforeunload 存数据
beforeunload 是唯一能拦截关闭/刷新的时机,但它只允许同步返回字符串,无法发请求或 await。
- 定义全局标志:
let hasUnsavedChanges = false;每次输入开始时设为true,防抖存完后设为false -
beforeunload回调中只做判断:if (hasUnsavedChanges) return '',触发浏览器默认提示 - 真正写入动作必须在防抖函数内部完成,不能拖到卸载钩子中
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











