用 watcheffect 实现未保存草稿警告,关键在于将表单修改状态转为响应式依赖并自动同步:通过 ref 存储初始快照与当前编辑值,watcheffect 自动追踪字段访问并比对差异更新 hasunsavedchanges,再结合 beforeunload 事件和 onbeforeunmount 清理实现完整提示逻辑。

用 watchEffect 实现未保存草稿的警告标记自动同步,关键在于把“用户是否修改过表单”这个状态转化为响应式依赖,并在变化时实时更新页面顶部或关闭页签前的提示逻辑。它不需要手动列字段、不依赖 mounted 钩子,改完即生效。
把表单值桥接到响应式状态
原始表单数据(如来自 API 的初始值)和当前编辑值必须能被 Vue 追踪。推荐做法是:用 ref 或 reactive 存储初始快照,再用另一个 ref 存当前编辑值;或直接用 toRefs 解构表单对象,确保每个字段可响应。
- 避免直接监听原生 DOM input 的 value —— 它不是响应式数据
- 所有输入操作都应更新响应式变量(如
form.title = e.target.value) - 初始快照建议深拷贝(
JSON.parse(JSON.stringify(raw))或使用结构化克隆),防止引用污染
用 watchEffect 自动比对并设置警告状态
在 setup 中定义 hasUnsavedChanges = ref(false),然后在 watchEffect 内部读取当前值与初始快照的差异。Vue 会自动追踪你访问的每一个响应式字段:
- 只要在函数体内写了
form.title、form.content等字段访问,它们就成为依赖 - 每次任一字段变化,watchEffect 就重新执行比对逻辑
- 比对结果直接赋给
hasUnsavedChanges.value,模板中用v-if="hasUnsavedChanges"即可显示横幅或星号标记
处理页面卸载前的强制校验
浏览器原生的 beforeunload 事件需要同步返回字符串才能触发提示。watchEffect 本身不接管这个事件,但可以配合它做准备:
- 在 watchEffect 外部注册
window.addEventListener('beforeunload', ...) - 事件处理器里只检查
hasUnsavedChanges.value,为 true 才返回提示文本 - 注意:该事件不能异步,所以不要在里面 await 或调用 API
- 组件卸载时记得移除监听器(可用
onBeforeUnmount清理)
避免误触发与性能干扰
某些操作(如格式化输入、自动补全)可能频繁修改字段但不构成“实质变更”,可加一层轻量防抖或语义判断:
- 比对前先做浅层 diff,跳过空格、换行等不影响内容的修改
- 对富文本编辑器等复杂字段,用
computed提取纯文本摘要再比对 - 若表单字段极多,可将比对逻辑封装为函数,在 watchEffect 中调用,保持副作用体简洁
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










