表单自动保存需以 watch 触发、localStorage 存储,按字段粒度监听,配合防抖、beforeunload 兜底、onMounted 恢复、版本控制及敏感字段过滤,并提供手动清除入口。

watch 本身不存数据,它只负责“发现变化”。要实现表单自动保存到缓存,关键是以 watch 为触发开关,配合 localStorage 完成写入、读取、防抖和恢复全流程。
监听字段变化并安全写入 localStorage
不要监听整个表单对象,优先按业务字段粒度监听,减少无效序列化开销。例如:
- 监听单个 ref:watch(formName, (newVal) => { localStorage.setItem('formName', JSON.stringify(newVal)); });
- 监听多个字段组合:watch([fieldA, fieldB], ([newA, newB]) => { localStorage.setItem('formAB', JSON.stringify({ a: newA, b: newB })); });
- 避免存函数、undefined、Date 或循环引用;简单方案是用 JSON.stringify 前做白名单过滤,或现代环境用 structuredClone 预处理
加防抖防止高频写入卡顿
用户连续输入时,每敲一个键都写 localStorage 会拖慢体验,尤其在低端设备上。必须加防抖控制频率:
- 手写简易防抖(无需引入库):const debounce = (fn, delay) => { let timer; return () => { clearTimeout(timer); timer = setTimeout(fn, delay); }; };
- 绑定到 watch 回调:const saveDebounced = debounce(() => localStorage.setItem('formCache', JSON.stringify(formValue)), 600); watch(formValue, () => saveDebounced());
- 补充兜底:在 beforeunload 钩子中强制执行一次保存,确保最后修改不丢失
页面加载时自动恢复缓存数据
持久化的意义是“下次打开还在”,所以初始化阶段必须读取并还原:
- 在 onMounted 中执行:onMounted(() => { const cached = localStorage.getItem('formCache'); if (cached) Object.assign(formValue, JSON.parse(cached)); });
- 注意类型限制:JSON.parse 无法还原 Date、Map、Set 等,但对字符串、数字、布尔、数组、扁平对象完全适用
- 可加版本号字段(如 cacheVersion: '1.3')便于后续缓存迁移或强制清旧
提供清除缓存的可控入口
不能只写不删。用户可能想重填,或敏感字段不宜长期留存:
- 暴露清除方法:const clearCache = () => { localStorage.removeItem('formCache'); formValue.value = { name: '', email: '' }; };
- 在 UI 上添加“清空草稿”按钮,并确认提示,兼顾体验与安全性
- 对密码、身份证等字段,建议从缓存白名单中直接排除,不参与自动同步










