Vue中的nextTick源码解析

189 阅读1分钟

**前置知识:**在了解nextTick原理之前需要先去学习下js事件循环相关的知识,因为nextTick是利用该机制实现的。

nextTick源码目录:

源码解析:

1.首先定义了全局的callbacks数组、pending状态、isUsingMicroTask、flushCallbacks函数和timerFunc函数。

2.其次会去判断浏览是否支持微任务如果支持就使用微任务不支持则去判断是否可用宏任务,判断的顺序是promise->MutationObserver->setImmediate->setTimeout。然后会将flushCallbacks函数放到微任务或者宏任务中并封装成函数赋值给timerFunc函数,如:

  // 浏览器支持promise
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true //设置为true表示使用微任务
  
  //支持MutationObserver
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, { //observer监听textNode的变化
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter) //textNode.data的值一发生变化observer回调函数就会执行
  }
  isUsingMicroTask = true
  
  //支持setImmediate
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
  
  //支持setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }

3.接下来就是暴露出去的nextTick函数。

(1)函数内部会先判断cb函数是否存在,若存在会用全局的callbacks数组收集cb函数的执行并且包裹在try catch中防止cb函数执行报错,阻塞了代码的执行。若不存在会判断_resolve的存在,一旦存在则执行_resolve()。

(2)判断全局的pending状态为false的情况下将pending设置为true,然后执行timerFunc函数

(3)timerFunc函数将异步执行flushCallbacks函数,函数将pending设置为false,然后浅拷贝callbacks,再清空callbacks,执行拷贝数组中的每个函数。