watch本身不负责持久化,仅监听数据变化;需结合localStorage实现自动保存,关键包括按字段粒度监听、JSON安全序列化、防抖控制、beforeunload兜底、onMounted时恢复数据、版本管理、清除机制及try-catch容错。
watch 本身不负责持久化,它只是监听数据变化的工具。真正实现“自动保存到 localStorage”,需要把 watch 当作触发器,配合 localStorage 完成写入和恢复动作。核心在于监听时机、防抖控制、安全序列化和初始化加载。
监听表单字段并触发保存
对响应式数据(如 ref 或 reactive 对象)使用 watch,在值变更后调用 localStorage.setItem。避免监听整个大对象,优先按字段粒度监听,减少冗余操作和性能损耗。
- 监听单个 ref:watch(formValue, (newVal) => { localStorage.setItem('formCache', JSON.stringify(newVal)); }, { deep: true });
- 监听多个字段可合并:watch([fieldA, fieldB], ([newA, newB]) => { /* 合并保存逻辑 */ });
- 确保 newVal 可被 JSON 安全序列化——过滤掉函数、Symbol、undefined 和循环引用;简单场景可用 JSON.stringify,复杂结构建议加白名单校验或用 structuredClone 预处理
加入防抖防止高频写入
用户连续输入时,频繁写 localStorage 不仅低效,还可能卡顿主线程,尤其在低端设备上。必须引入防抖机制。
- 用 lodash.debounce 或手写简易防抖函数包裹保存逻辑,例如延迟 800ms 执行
- 在离开页面前(beforeunload 事件)强制触发一次保存,兜底保障最后修改不丢失
页面加载时自动恢复数据
持久化的意义是“下次打开还能看见”。需在组件挂载时读取 localStorage,并还原到表单状态中。
- 推荐在 onMounted 中执行:const cached = localStorage.getItem('formCache'); if (cached) Object.assign(formValue, JSON.parse(cached));
- 注意 JSON.parse 会丢失 Date、Map、Set 等类型,普通字符串/数字/布尔/数组/扁平对象一般无影响
- 可增加版本号字段(如 cacheVersion: '1.3'),便于后续做缓存迁移或强制失效
提供清除与容错能力
不能只存不删,也不能忽略异常。用户可能想清空草稿,或浏览器限制导致写入失败。
- 暴露 clearCache 方法:const clearCache = () => { localStorage.removeItem('formCache'); formValue.value = { /* 重置默认值 */ }; };
- 所有 localStorage 操作必须包裹 try-catch,捕获 QuotaExceededError 或 DOMException
- 读取时先判断是否为 null,避免 JSON.parse 报错;解析失败应返回默认值而非中断流程