You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 23:37:35