VUE逐点突破系列 -- nextTick实现原理

本文探讨Vue的nextTick机制,详细解释了Vue如何通过异步队列策略处理数据变更,避免频繁更新。在事件循环的下一个tick中,Vue会执行已去重的工作,源码中涉及Promise、MutationObserver和setTimeout等实现方式。文章通过分析nextTick的流程,展示了如何从数据修改到组件更新的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VUE逐点突破系列 – nextTick实现原理

  1. vue有个批量、异步更新策略,数据变化时,vue开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。然后在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

  2. 源码中,修改一个数据,组件对应的watcher会尝试入队:

queue.push(watcher)

并使用nextTick方法添加一个flushSchedulerQueue回调

nextTick(flushSchedulerQueue)

flushSchedulerQueue被加入callbacks数组

callbacks.push(() => {
  if (cb) {
    try {
      cb.call(ctx) // cb就是加入的回调
    } catch (e) {
      handleError(e, ctx, 'nextTick')
    }
  } 
})

然后以异步方式启动

if (!pending) {
  pending = true
  timerFunc()
}

timerFunc的异步主要利用Promise等微任务方式实现

let timerFunc

if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  // timerFunc利用p.then向微任务队列添加一个flushCallbacks
  // 会异步调用flushCallbacks
  timerFunc = () => {
    p.then(flushCallbacks)
  }
  isUsingMicroTask = true
}

flushCallbacks遍历callbacks,执行里面所有回调

function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

其中就有前面加入的flushSchedulerQueue,它主要用于执行queue中所有watcher的run方法,从而使组件们更新

for (index = 0; index < queue.length; index++) {
  watcher = queue[index]
  watcher.run()
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值