Vue Composition API:监听对象新旧值一致?flush选项作用解析
关于Vue Watch中
flush选项的详细解析 首先得说清楚:你碰到的新旧值打印一致的情况,本质是因为你监听的是引用类型(数组里的对象),Vue的watch默认不会对旧值做深拷贝,所以新旧值指向的是同一个内存地址——不过flush选项管的是watch回调什么时候执行,这也是它三个可选值的核心区别,下面我逐个给你拆解:
1. flush: 'pre'(默认值)
- 执行时机:在组件更新之前触发回调。
- 实际表现:
- 当你修改响应式数据后,watch回调会先于Vue更新DOM执行。
- 这时候如果在回调里操作DOM,拿到的还是更新前的旧DOM状态。
- 回到你的代码,用
pre的话,changeName修改名字后,watch会在组件DOM还没更新的时候就打印数据,虽然新旧值还是同一个引用,但触发时机更早。
2. flush: 'post'
- 执行时机:在组件更新完成之后触发回调。
- 实际表现:
- 回调会等Vue把DOM更新完再执行,这时候你能拿到最新的DOM状态(比如修改后的元素内容、尺寸)。
- 还是要强调:你现在看到新旧值一致,和
post无关,是因为监听的是引用类型——新旧值指向同一个数组对象,不管flush选啥,这个情况都存在,除非你手动拷贝旧值。
- 适合场景:当你的回调需要依赖更新后的DOM时(比如要获取新渲染出来的列表高度),就用这个选项。
3. flush: 'sync'
- 执行时机:同步触发,数据一变立刻执行回调,完全跳过Vue的异步更新队列。
- 实际表现:
- 不同于
pre和post会把回调放进异步更新队列攒着批量执行,sync会在数据变化的同一瞬间就跑回调。 - 注意:别乱用这个选项!频繁触发同步回调会打破Vue的批量更新优化,导致性能下降,只有万不得已(比如必须立刻拿到变化后的数据去做同步操作)才用。
- 不同于
额外补充:怎么拿到真正的旧值?
如果你想在watch里拿到修改前的真实旧值,得手动对引用类型做深拷贝保存,比如:
setup(){ const users = ref([{ name: 'John' }]); // 初始化时保存旧值的深拷贝 let oldUsersSnapshot = JSON.parse(JSON.stringify(users.value)); const changeName = () => { users.value[0].name = 'Alex'; }; watch( () => users.value, (newVal) => { console.log('新值:', newVal, '旧值:', oldUsersSnapshot); // 更新快照,下次变化时用 oldUsersSnapshot = JSON.parse(JSON.stringify(newVal)); }, { lazy: false, deep: true, flush: 'post' } ); return { users, changeName }; }
这样就能拿到真正的新旧值对比了,而flush只是控制这个打印动作在DOM更新前还是后执行而已。
内容的提问来源于stack exchange,提问作者DanielZ
相关产品推荐
相关产品推荐

