核心是用 watch 监听表单状态快照差异来判断是否已修改,需初始化深拷贝快照、深度监听并标准化非原始类型值,提交后重置状态,结合路由守卫防丢失修改。

核心是用 watch 监听表单状态快照差异,而不是逐个字段监听。关键不在“监听动作”,而在“如何定义‘已修改’”——即当前值是否偏离了初始快照。
监听整个表单对象(推荐)
适合表单数据集中管理(如一个 reactive 或 ref 对象)。重点在于初始化快照和稳定比对:
- 页面加载后立即用
structuredClone(form)或JSON.stringify(form)保存初始值,避免引用赋值 - 用
watch(form, () => { isDirty.value = !isEqual(form, initialForm); }, { deep: true })深度监听变化 - 提交成功后,重置
isDirty.value = false并更新initialForm快照 - 若不用 Lodash,可用简易对比:对 Date/Array/Object 字段先标准化(如
new Date().toISOString()、JSON.stringify())再比较字符串
监听多个独立 ref(适合分散定义)
当表单字段是单独的 ref(如 usernameRef、emailRef),可用数组批量监听:
- 定义
const formRefs = [usernameRef, emailRef, ageRef] watch(formRefs, () => { isDirty.value = true; }, { deep: true })- 首次赋值会触发 watch,建议在
onMounted后启用,或加标记跳过初始化阶段 - 忽略只读字段、计算属性、UI 状态(如
loading、showPassword)
防误判与边界处理
用户没改内容,但引用变了(比如日期选中后生成新 Date 实例),会导致 isDirty 错误为 true:
- 对非原始类型字段,在监听前做标准化处理(日期转 ISO 字符串、对象序列化)
- 提交失败或用户取消编辑时,提供“还原初始值”按钮,手动同步
form和initialForm - 路由离开前检测
isDirty.value === true,用onBeforeRouteLeave阻止跳转并弹出确认提示
结合路由守卫自动提示
防止用户意外丢失修改:
- 组件内使用
onBeforeRouteLeave((to, from, next) => { if (isDirty.value) { const confirmed = window.confirm('有未保存的修改,确定离开?'); confirmed ? next() : next(false); } else next(); }) - 注意:浏览器限制非用户手势触发的
confirm,生产环境建议用自定义弹窗 + 手动控制路由跳转 - 确保
isDirty是响应式变量(如ref(false)),并在所有修改入口(输入、选择、切换)保持统一更新逻辑
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











