关于nextTick的解析
这里就涉及到Vue中对DOM的更新策略了,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个事件队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到事件队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新事件队列并执行实际 (已去重的) 工作。 这里我理解的是 不可能所有DOM的更新都会马上执行 因为每一轮事件循环中涉及到多出更新DOM 因此在VUE内部 DOM 都是在一轮事件循环之后 下一轮循环之前开始然后处理上一轮遗留的所有DOM操作 一起进行更新 具体源码参考https://juejin.cn/post/6844904147804749832 主要步骤:- 将nextTick中定义的回调函数全部放置到callbacks数组中; 内部形成一个闭包 数组内存不释放 始终添加回调 只有在第一次添加回调函数的时候会加一个pending 执行timeFunc 避免多次执行。
- 执行timeFunc函数;其中timeFunc函数是简要说明是执行异步操作 如果js支持promise 则是promise异步回调函数;
- 这个异步回调用于依次执行callbacks中的函数; DOM更新是同步到 这样拿到的DOM就是最新的
export let isUsingMicroTask = false if (typeof Promise !== 'undefined' && isNative(Promise)) { //判断1:是否原生支持Promise const p = Promise.resolve() timerFunc = () => { p.then(flushCallbacks) if (isIOS) setTimeout(noop) } isUsingMicroTask = true } else if (!isIE && typeof MutationObserver !== 'undefined' && ( isNative(MutationObserver) || MutationObserver.toString() === '[object MutationObserverConstructor]' )) { //判断2:是否原生支持MutationObserver let counter = 1 const observer = new MutationObserver(flushCallbacks) const textNode = document.createTextNode(String(counter)) observer.observe(textNode, { characterData: true }) timerFunc = () => { counter = (counter + 1) % 2 textNode.data = String(counter) } isUsingMicroTask = true } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { //判断3:是否原生支持setImmediate timerFunc = () => { setImmediate(flushCallbacks) } } else { //判断4:上面都不行,直接用setTimeout timerFunc = () => { setTimeout(flushCallbacks, 0) } }说的diff算法比较好 https://segmentfault.com/a/1190000008782928