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

Promise修改Vue响应式数据:位置为何影响onUpdated触发次数?

问题分析:两种写法触发onUpdated次数不同的原因

先看两种写法的代码:

第一种写法

const list = reactive([1, 2, 3, 4, 5]); 
const handleClick = () =>{
    list.push(...[11, 12, 13, 14, 15]);
    list.push(...[16, 17, 18, 19, 20]);
    Promise.resolve().then(() => {
        list.push(33)
    });
};

第二种写法

const list = reactive([1, 2, 3, 4, 5]);
const handleClick = ()=>{
    Promise.resolve().then(() => {
        list.push(33)
    });
    list.push(...[11, 12, 13, 14, 15]);
    list.push(...[16, 17, 18, 19, 20]);
};

核心原因:Vue异步批量更新机制 + 微任务执行顺序

Vue的响应式更新是异步批量处理的:同步修改响应式数据时,Vue不会立刻更新DOM,而是把所有更新操作放到队列里,等当前同步代码执行完后,通过微任务一次性批量处理队列更新,触发一次onUpdated钩子。

第一种写法的执行流程

  1. 同步代码先执行两次list.push,这两次修改被Vue加入同一个更新队列,同时Vue调度一个更新微任务。
  2. 接着注册Promise的then回调,这个回调作为另一个微任务,排在更新微任务之后。
  3. 同步代码执行完后,事件循环处理微任务:
    • 先执行Vue的更新微任务:批量处理两次push的更新,DOM更新完成,触发第一次onUpdated,此时更新队列清空。
    • 再执行Promise的then回调:修改list.push(33),Vue发现没有待处理的更新任务,重新调度一个新的更新微任务。
    • 新的更新微任务执行时,处理push(33)的更新,DOM再次更新,触发第二次onUpdated。

第二种写法的执行流程

  1. 同步代码先注册Promise的then回调,这个回调作为微任务A加入队列。
  2. 接着执行两次list.push,这两次修改被Vue加入更新队列,同时Vue调度一个更新微任务B,排在微任务A之后。
  3. 同步代码执行完后,事件循环处理微任务:
    • 先执行微任务A:修改list.push(33),此时Vue发现已有待处理的更新微任务B,就把这次push(33)的更新直接加入现有更新队列,不新增微任务。
    • 再执行微任务B:Vue批量处理所有三次更新(两次push + push(33)),一次性完成DOM更新,只触发一次onUpdated。

简单说,第二种写法里Promise回调的修改赶上了同步代码触发的更新队列,被合并成一次更新;第一种写法里Promise回调的修改是在第一次更新完成后才触发的,只能单独触发一次新的更新。

内容的提问来源于stack exchange,提问作者KimSohyun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:25:12