源码:
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]()
}
}
if (typeof Promise !== 'undefined' && isNative(Promise)) {
var p = Promise.resolve()
var logError = err => { console.error(err) }
timerFunc = () => {
p.then(nextTickHandler).catch(logError)
if (isIOS) setTimeout(noop)
}
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
isNative(MutationObserver) ||
MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
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 {
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用于延迟执行一段代码,它接收2个参数:回调函数和执行回调函数的上下文环境(也就是ctx,全名Execution Context),如果没有提供回调函数,那么将返回promise对象。
至于为何需要延时执行一段代码,vue官方也给过解释:
Vue 异步执行 DOM 更新。只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
首先它定义了三个变量,
callbacks:存储需要执行的回调函数;
pending:标记是否正在执行回调函数;
timerFunc:触发执行回调函数;
下面是nextTickHandler函数,用来给timerFunc赋值 并执行callbacks中存储的所有回调函数。
接下来上了个大判断,vue会按照最优方案去触发回调:
1,是否支持promise,如果是,则使用promise来执行回调函数;
2,是否支持MutationObserver,如果是,则使用MutationObserver来执行回调函数,这是H5新增的一个API,用来监视DOM变动;
3,如果前两者都不支持,那就用最后的老伙计,setTimeout来执行,并设置延时为0。
最后返回一个queueNextTick函数 ,这里接收的即是用户输入的回调函数和执行上下文,并且将回调函数存入callbacks中。(queue是队列的意思)
所以其实整个nextTick函数先执行的是queueNextTick,然后用timerFunc进行延时,最后用nextTickHandler执行函数。
本文详细解析Vue.js中nextTick函数的工作原理,包括其内部实现机制及如何通过不同技术手段延迟执行DOM更新。

2954

被折叠的 条评论
为什么被折叠?



