阅读 60

Vue nextTick 的实现

看了一些vue nextTick引发的bug, github.com/DDFE/DDFE-b… github.com/vuejs/vue/i… 实际上,vue在macrotask 和 microtask的问题上反复好久,有时micro 优先,有时 macro 优先,有时可以指定谁优先。

引发问题的原因是因为event冒泡的优先级小于microtask,用macro task 对transitions的执行有影响。

nextTick的代码是维护了一个callbacks队列,dep数据更新之后触发的操作会push到callbacks中,然后把callbacks的callback挨个执行,nextTict分为两种调用方式,带参数cb的和不带cb的。带cb的会把用户的cutom cb放到callbacks队列最后执行,不带cb参数的会返会一个promise,并在callbasks执行完成后resovled。

我实现了一个microtask的nectTick,不考虑schedule函数的细节,只看看它做了什么


const callbacks = []
let pending = false

function flushCallbacks() {
  return Promise.resolve().then(() => {
    pending = false
    const copies = callbacks.slice(0)
    callbacks.length = 0
    for (let i = 0; i < copies.length; i++) {
      console.log('copy i', i, 'copies length', copies.length)
      copies[i]()
    }
  })
}

function nextTick(callback) {
  let _resolve
  console.log('callbacks length', callbacks.length)
  callbacks.push(() => {
    if (callback) {
      callback.call()
    } else if (_resolve) {
      _resolve()
    }
  })

  console.log('pending', pending)
  if (!pending) {
    pending = true
    flushCallbacks()
  }

  if (!callback) {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}

function test1() {
  console.log('test1')
}

function test2() {
  console.log('test2')
}

nextTick(test1)
nextTick(test2)
nextTick(test2)
nextTick(test2)
nextTick(test2)

复制代码

其中有一点没想明白,flushCallbacks 中为什么要复制一遍callbacks,而不是在callbacks执行完成后再清空它。请各位不吝赐教。

文章分类
前端
文章标签