不能直接用change或submit存草稿,因change需失焦才触发、submit仅在点击时发生且易因校验失败或超时导致未保存;应采用input事件配合防抖,并精准监听有效字段、带上下文命名键名、确保dom就位后恢复并派发事件。

为什么不能直接用 change 或 submit 事件存草稿
用户粘贴大段文字、用中文输入法选词、在 textarea 里快速滚动编辑时,change 根本不触发——它必须失焦;而 submit 只在点击按钮时发生,关页、刷新、切标签就全丢了。更危险的是,有人在 submit 回调里调 localStorage.setItem(),结果表单校验失败或网络超时,草稿压根没存进去。
用 input + 防抖才是实际可行的组合
防抖不是可选项,是保底手段:中文输入法下,敲“shanghai”会连续触发十几次 input,不加防抖就会把“sha”“shang”“shangh”全写进 localStorage,最后覆盖掉用户真正想存的完整内容。
- 手写防抖即可,不用引入库:
let timeoutId; form.addEventListener('input', e => { clearTimeout(timeoutId); timeoutId = setTimeout(() => saveDraft(form), 800); }) - 只监听有效字段:
input、textarea、select,以及type="checkbox"或type="radio"的input;跳过type="hidden"、type="password"、disabled元素 - 键名必须带上下文,比如
draft-${form.id || 'default'}-${location.pathname},否则两个同名表单会互相擦除
恢复草稿时 DOM 还没出来,怎么办
很多代码在 DOMContentLoaded 里遍历 form.elements 填值,但 Vue/React 组件或 AJAX 加载的表单此时 DOM 根本不存在,结果静默失败,用户以为“没恢复”,其实是“根本没试”。
- 原生 JS 场景:等
form元素真实挂载后再操作,可用form.offsetParent !== null或 MutationObserver 监听子节点插入 - 填值前必须检查字段是否还存在:
if (el && 'value' in el),对checkbox/radio单独处理:el.checked = Boolean(data[el.name]) - 填完立刻派发事件:
el.dispatchEvent(new Event('input', { bubbles: true })),否则 Vue 的v-model、React 的受控组件完全无感知
formnovalidate 不生效?先确认这三件事
点“暂存”按钮仍弹浏览器原生提示“请填写此字段”,大概率不是属性写错了,而是结构或调用方式不对。
- 按钮必须在
form标签内,且显式声明type="submit";写成type="button"或漏写type,formnovalidate就被忽略 - 如果按钮在表单外,要用
form="form-id"显式关联,不能只靠 DOM 位置 - 别用
form.submit()触发——它无视formnovalidate;改用form.requestSubmit(),它尊重该属性且只走一次校验逻辑
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











