HTML5文章编辑器自动保存需用localStorage+防抖(800ms),键名唯一(如"draft-article-"+id),存结构化对象并序列化,DOM就绪后恢复且校验时间戳。

在HTML5中实现文章编辑器的自动保存,核心是用 localStorage 持久缓存内容,再通过防抖控制写入频率,避免高频触发、中间态覆盖和性能卡顿。关键不在“能不能存”,而在于“什么时候存、存什么、怎么取、怎么清”四个环节严丝合缝。
监听输入并加防抖,避开中文输入法陷阱
直接绑定 input 事件并立刻调用 localStorage.setItem() 是最常见也最危险的做法——中文输入法下,“zhong”会连续触发“z”“zh”“zho”等十几次,把未选词的碎片内容写进存储,还可能阻塞主线程导致卡顿。
- 用
setTimeout+clearTimeout手写防抖,延迟 800ms 再保存:用户停笔即落盘,既适配输入法节奏,又保障最后输入不丢失 - 每次新输入先清除上一个定时器,仅当内容实际变化(与上次保存值
!==)才执行写入 - 跳过
type="password"、data-no-autosave等敏感或禁用字段,不存空字符串或纯空白
设计带上下文的键名与结构化数据
用固定 key(如 "draft")会导致多标签页、多文章页互相覆盖;只存纯文本则无法判断时效、来源和状态。
- 键名推荐格式:
"draft-article-" + articleId或"draft-" + location.pathname + "-" + Date.now().toString(36),确保唯一性 - 存对象而非字符串:
{ content: "用户输入", title: "未命名", savedAt: Date.now(), updatedAt: Date.now() } - 必须用
JSON.stringify()序列化后再写入,读取时配套JSON.parse(),否则会报Unexpected token u
页面加载后安全恢复,兼容框架与动态渲染
DOM 还没挂载就执行恢复逻辑,结果就是“读到了,但填不进去”。尤其 Vue/React 表单或 AJAX 加载的内容,容易因时机错位导致草稿“看不见”。
立即学习“前端免费学习笔记(深入)”;
- 恢复操作必须放在
DOMContentLoaded后,或更稳妥地配合框架钩子(如 Vue 的mounted、React 的useEffect(() => {}, [])) - 先检查元素是否存在:
if (el && el.value !== undefined),再赋值;对contenteditable元素用el.innerText = data.content(防 XSS),富文本需存innerHTML并做白名单过滤 - 填完手动派发事件:
el.dispatchEvent(new Event('input', { bubbles: true })),否则 v-model 或受控组件不会响应 - 恢复前校验时间戳:
Date.now() - data.savedAt ,超 24 小时的草稿默认不还原
提交与退出时及时清理,兜底 beforeunload
草稿不是永久资产。不清理会导致已提交内容反复弹出,干扰用户;不兜底则关页前最后一笔可能丢失。
- 表单成功提交后,立即执行
localStorage.removeItem(key) - 用户点击“放弃编辑”或“清空草稿”时同步删除
-
beforeunload中只做两件事:检查hasUnsavedChanges === true,并返回提示字符串(如"内容尚未保存,确定要离开?");它不能执行异步操作,也不该承担保存任务——真正保存必须已在防抖中完成 - 写入前加
try/catch,捕获QuotaExceededError(尤其 iOS Safari 无痕模式),降级为内存缓存或提示用户手动复制



















