nextTick源码浅析

使用

      this.$nextTick(() => {
        this.msg2 = this.$refs.msgDiv.innerHTML
      })

作用

Vue.nextTick用于延迟执行一段代码,它接受2个参数(回调函数和执行回调函数),如果没有提供回调函数,那么将返回promise对象。

源码

/**
 * Defer a task to execute it asynchronously.
 */
export const nextTick = (function () {
  const callbacks = []
  let pending = false
  let timerFunc

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

  // the nextTick behavior leverages the microtask queue, which can be accessed
  // via either native Promise.then or MutationObserver.
  // MutationObserver has wider support, however it is seriously bugged in
  // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It
  // completely stops working after triggering a few times... so, if native
  // Promise is available, we will use it:
  /* istanbul ignore if */
  if (typeof Promise !== 'undefined' && isNative(Promise)) {
    var p = Promise.resolve()
    var logError = err => { console.error(err) }
    timerFunc = () => {
      p.then(nextTickHandler).catch(logError)
      // in problematic UIWebViews, Promise.then doesn't completely break, but
      // it can get stuck in a weird state where callbacks are pushed into the
      // microtask queue but the queue isn't being flushed, until the browser
      // needs to do some other work, e.g. handle a timer. Therefore we can
      // "force" the microtask queue to be flushed by adding an empty timer.
      if (isIOS) setTimeout(noop)
    }
  } else if (!isIE && typeof MutationObserver !== 'undefined' && (
    isNative(MutationObserver) ||
    // PhantomJS and iOS 7.x
    MutationObserver.toString() === '[object MutationObserverConstructor]'
  )) {
    // use MutationObserver where native Promise is not available,
    // e.g. PhantomJS, iOS7, Android 4.4
    var counter = 1
    var observer = new MutationObserver(nextTickHandler)
    var textNode = document.createTextNode(String(counter))
    observer.observe(textNode, {
      characterData: true
    })
    timerFunc = () => {
      counter = (counter + 1) % 2
      textNode.data = String(counter)
    }
  } else {
    // fallback to setTimeout
    /* istanbul ignore next */
    timerFunc = () => {
      setTimeout(nextTickHandler, 0)
    }
  }

  return function queueNextTick (cb?: Function, ctx?: Object) {
    let _resolve
    callbacks.push(() => {
      if (cb) {
        try {
          cb.call(ctx)
        } catch (e) {
          handleError(e, ctx, 'nextTick')
        }
      } else if (_resolve) {
        _resolve(ctx)
      }
    })
    if (!pending) {
      pending = true
      timerFunc()
    }
    if (!cb && typeof Promise !== 'undefined') {
      return new Promise((resolve, reject) => {
        _resolve = resolve
      })
    }
  }
})()
### 查找 `nextTick` 源码实现 #### Node.js中的`process.nextTick` Node.js 中的 `process.nextTick` 是一种机制,用于在当前操作完成后立即将回调推入“检查”阶段之前执行。这意味着它会在事件循环的下一个迭代中尽早处理这些回调。 ```javascript const callback = () => { console.log('This will be processed after the current operation completes'); }; process.nextTick(callback); console.log('This is the first output.'); ``` 这段代码会先输出 "This is the first output." ,然后才是回调函数内的日志[^1]。 然而,在 Vue.js 上下文中讨论的是另一种形式的 `nextTick` 实现方式。Vue 的 `nextTick` 并不是直接调用了 Node.js 的 `process.nextTick` 函数,而是为了适应浏览器环境设计的一种异步更新队列机制。 #### Vue.js中的`nextTick` 对于 Vue 来说,`nextTick` 主要是为了确保当状态改变时能够正确地等待 DOM 更新完毕再执行特定逻辑而存在的工具方法。其核心在于利用 JavaScript 的微任务 (microtask) 和宏任务 (macrotask),以及浏览器重绘特性来安排合适的时机触发回调。 具体来说: - 如果存在原生 Promise,则优先采用Promise.resolve().then()的方式创建一个微任务; - 否则依次尝试 MutationObserver 或 setImmediate/setTimeout(0)等方式模拟类似的延迟效果[^3]。 以下是简化版的伪代码表示: ```javascript function nextTick(cb){ let callbacks; function flushCallbacks(){ while(callbacks.length){ const fn=callbacks.shift(); try{ fn(); }catch(e){ // handle error... } } } if(!pending){ // pending用来防止重复刷新 pending=true; if(useMicroTask){ /* 使用 promise 创建 micro task */ Promise.resolve().then(flushCallbacks); }else{ setTimeout(flushCallbacks,0); } } callbacks.push(cb); } ``` 此版本省去了部分细节以便更好地展示整体流程。实际源码位于 `src/core/util/next-tick.js` 文件内,并且包含了更多优化措施以提高性能和兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力,加油,奋斗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值