必须防抖保存,因中文输入法高频触发存拼音碎片、低端设备静默拒绝写入、多行共用key致覆盖、DOM未就位导致获取失败;键名需含稳定上下文如data-id,恢复时须DOM就位+手动派发input事件。

表格内 textarea 必须加防抖、带上下文键名、DOM 就位后恢复、手动派发事件——否则刷新即丢,中文输入存拼音碎片,Vue/React 不响应。
为什么直接监听 input 并立刻 localStorage.setItem() 会失效
表格里每个 textarea 都是动态插入或复用的 DOM 节点,一敲就存会导致:
- 中文输入法下高频触发(“sh”“sha”“shang”连续十几次),存进 localStorage 的是未完成的拼音中间态
- 低端安卓机或 Safari 隐私模式可能静默拒绝写入,不报错也不存
- 多个表格行共用同一 key(如
"draft"),后编辑的行覆盖前一行草稿 - 没等表格渲染完就执行保存逻辑,
querySelectorAll('textarea')返回空 NodeList
怎么给表格里的 textarea 加防抖保存
防抖不是可选项,是必须项。800ms 是兼顾输入法节奏和用户感知的合理延迟。
- 每个
textarea绑定input事件,但不立刻存,而是用setTimeout+clearTimeout手写防抖 - 键名必须含表格上下文,例如:
`draft-table-${tableId}-row-${rowIndex}`,避免跨行污染 - 只在值实际变化时才写入:
if (el.value !== lastSavedValue) localStorage.setItem(key, el.value) - 跳过带
data-no-autosave属性或type="password"的字段
页面加载后怎么安全恢复表格草稿
恢复失败八成是因为时机错了——DOM 还没挂载,或框架还没接管。
立即学习“前端免费学习笔记(深入)”;
- 原生 JS:等
DOMContentLoaded后再执行;若表格是 AJAX 渲染,需监听自定义事件(如'table-ready') - Vue/React:在
mounted或useEffect(() => {}, [])里读取localStorage.getItem(key) - 填值前先检查元素是否存在:
if (el && 'value' in el) el.value = draft - 填完必须手动派发事件:
el.dispatchEvent(new Event('input', { bubbles: true })),否则 v-model 或受控组件无感知 - 对空字符串也要恢复(用户清空后刷新不该回填旧值),但要跳过
null或undefined
beforeunload 里只能做提示,不能存数据
这个钩子唯一能干的事,就是告诉浏览器:“用户有未保存内容”,它不接受异步、不支持 await、不允许 fetch。
- 提前设一个标志位:
let hasUnsavedChanges = false,每次 input 开始时设为true,防抖存完设为false -
beforeunload回调里只做判断:if (hasUnsavedChanges) return '您有未保存的编辑内容' - 现代浏览器已屏蔽自定义提示文字,只显示统一文案,所以别在回调里塞日志或埋点
- 真正存储动作必须在防抖结束那一刻完成,
beforeunload只是最后一道确认闸门
最易被忽略的点:表格行可能是复用的(比如虚拟滚动、分页重绘),rowIndex 会变,但草稿 key 没跟着更新——结果新行加载出来,恢复的是旧行的草稿。键名里的标识必须稳定可追溯,比如用每行数据的唯一 ID(data-id="user-123")代替索引。



















