富文本编辑器实时自动保存草稿需防抖+有效性判断+上下文隔离键名+内容与状态分离存储。监听input时避开输入法干扰,仅当current≠lastsavedvalue且非空才保存;键名用editor-content-${formid}和editor-state-${formid};恢复时先设内容再还原光标等状态。

富文本编辑器实时自动保存草稿时用防抖,关键不是“等几秒再存”,而是避开输入法干扰、防止无效写入、确保恢复可用。直接监听 input 立即存 localStorage,中文输入下会存拼音(如“nih”)、丢光标、刷新后内容还在但编辑功能瘫痪——这不是没保存,是存了也白存。
防抖必须配合有效性判断
只加 setTimeout 不够。用户敲“你好”又删掉重打,值没变,不该触发保存;否则既浪费 I/O,又可能把中间态当草稿存下来。
- 每次输入前记录上一次已保存的值:
lastSavedValue = editor.getValue() - 防抖回调里严格比对:
if (current !== lastSavedValue && current.trim() !== ''),满足才执行保存 - 保存成功后更新
lastSavedValue = current,形成闭环
键名要带上下文隔离
用固定 key(如 "draft")会导致多页、多编辑器互相覆盖。也不能用 Date.now() 或随机数——恢复时根本找不到。
- 推荐结构:
editor-content-${formId}(存 HTML 文本)、editor-state-${formId}(存光标、折叠行等 UI 状态) -
formId可取自元素id、URL 路径或哈希,例如:editor-content-/post/edit/123 - 密码框、验证码等字段加
data-no-autosave属性,自动跳过
恢复必须等 DOM 就绪并补发事件
页面刚加载时 JS 执行早于编辑器初始化,直接赋值会被清空;Vue/React 的双向绑定也不会响应。
- 读取时机:原生用
DOMContentLoaded,Vue 用mounted,React 用useEffect(() => {}, []) - 校验草稿:
if (draft !== null && draft.trim() !== ''),避免JSON.parse(null)报错 - 填完后手动派发:
el.dispatchEvent(new Event('input', { bubbles: true })),让框架感知变更
内容与状态必须分开存储
富文本的“状态”不是字符串的一部分:光标位置、选区、折叠行号、语法高亮标记……这些无法从 HTML 还原,必须单独提取、序列化、存进另一个 key。
- 纯内容走
editor-content-xxx,用innerHTML = draft或编辑器 API 设置(如 Quill 的setContents()) - UI 状态走
editor-state-xxx,存前调用编辑器方法获取,如 CodeMirror 的getCursor()、Monaco 的getSelection() - 恢复时先设内容,再调用编辑器 API 恢复光标/选区,顺序不能反
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











