实现 nextTick

简介: 利用微任务与宏任务,派发延时任务。Vue 中 nextTick 的原理。实现 nextTick。

为什么需要 nextTick

在同一段逻辑中,上半段我们更新了视图,下半段又依赖上半段更新完以后的新视图,同步执行上半段逻辑与下半段逻辑,那一定是不可行的,我们需要将下半段逻辑作为一个延时任务放到下一次事件循环中执行。读伪代码也许更有助理解:

function init() {
  createMessageContainer() // 更新视图
  message.open() // 使用新的视图。这里会报错,因为依赖上面更新完后得到的新视图
}

// 于是我们希望可以派发一个延时任务
function init() {
  createMessageContainer() // 更新视图
  nextTick(() => {
    message.open() // 使用新的视图
  })
}

我们希望 nextTick 可以接收一个回调函数,这个回调函数包裹了我们希望在这一次事件循环结束以后执行的逻辑。

那么如何实现这个 nextTick 就是我们讨论的重点。

如何实现 nextTick

nextTick 需要将传入的回调函数包装成异步任务,异步任务分为宏任务与微任务,为了尽快执行,所以应该优先选择微任务。但是我们也需要考虑兼容性,最后我们选用 API 的优先级如下:

  1. Promise
  2. MutationObserver
  3. setImmediate
  4. setTimeout
function nextTick(callback) {
  let timerFunc;
  if (Promise可用) {
    // 使用 Promise
  } else if (MutationObserver可用) {
    // 使用 MutationObserver
  } else if (setImmediate可用) {
    // 使用 setImmediate
  } else {
    // 微任务都不被支持,使用 setTimeout
  }
  timerFunc(); // 派发延时任务
}

有了设计思路,实现起来易如反掌:

function nextTick(callback) {
  let timerFunc;
  if (typeof Promise !== 'undefined') {
    const p = Promise.resolve();
    timerFunc = () => {
      p.then(callback);
    };
  } else if (
    typeof MutationObserver !== 'undefined' &&
    MutationObserver.toString() === '[object MutationObserverConstructor]'
  ) {
    let counter = 1;
    const observer = new MutationObserver(callback);
    const textNode = document.createTextNode(String(counter));
    observer.observe(textNode, { characterData: true });
    timerFunc = () => {
      counter = (counter + 1) % 2;
      textNode.data = String(counter); // 数据更新
    };
  } else if (typeof setImmediate !== 'undefined') {
    timerFunc = () => {
      setImmediate(callback);
    };
  } else {
    timerFunc = () => {
      setTimeout(callback, 0);
    };
  }
  timerFunc();
}

总结

读到这里你应该已经发现以上就是 Vue 中 nextTick 的原理了~

异步任务的巧妙使用可以帮助我们更好的玩转 JavaScript~

相关文章
|
6月前
|
JavaScript 前端开发
深入了解 Vue中$nextTick
$nextTick`是 Vue 框架中的一个函数,用于在 DOM 更新完成后执行回调函数。它的主要作用是`解决在 Vue 中修改数据后,DOM 不会立即更新的问题
|
JavaScript 前端开发
vue中nextTick()的理解及使用
vue中nextTick()的理解及使用
|
JavaScript
Vue中 使用定时器 (setInterval、setTimeout)
Vue中 使用定时器 (setInterval、setTimeout)
182 0
|
6月前
|
JavaScript API
在使用$nextTick方法时,需要注意哪些问题?
在使用$nextTick方法时,需要注意哪些问题?
46 0
|
6月前
|
JavaScript 调度
setTimeout和setImmediate以及process.nextTick的区别?
setTimeout和setImmediate以及process.nextTick的区别?
98 0
|
JavaScript
$nextTick使用
$nextTick使用
|
JavaScript 前端开发
vue3 nextTick()应用
在Vue3中,可以使用nextTick函数来延迟执行某些操作,这些操作会在下一次DOM更新周期之后执行。这个函数通常用于在数据更新后,等待DOM更新之后执行一些操作,比如获取DOM元素的尺寸、位置等。
|
JavaScript 前端开发
vue中的$nextTick?
vue中的$nextTick?
62 0