nextTick在vue官方解释是说在下次DOM更新循环结束后立即执行延迟回调,获取更新后的DOM
对于microtasks(微任务)和macrotasks(宏任务),vue在2.4版本之前一直用microtasks,但是它的优先级太高,在某些情况下可能会出现逼时间冒泡更快执行的情况;如果全部使用macrotasks,对于大数据DOM会出现渲染性能问题。所以在新版本中(vue版本超过2.4)默认使用microtasks,在特殊情况下会使用macrotask,比如在使用v-on绑定事件。
对于使用macrotasks,会先判断是否使用setImmediate,不能的话降级为MessageChannel,以上都不行,则使用setTimeout
if(typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
macroTimerFunc = () => {
setImmediate(flushCallbacks);
};
} else if(typeof MessageChaanel !== 'undefined' && (isNative(MessageChaanel) || MessageChaanel.toString() === '[object MessageChannelConstructor]')) {
const channel = new MessageChannel();
const port = channel.port2;
channel.port1.onmessage = flushCallbacks;
macroTimerFunc = () => {
port.postMessage(1);
};
} else {
macroTimerFunc = () => {
setTimeout(flushCallbacks, 0);
}
}
同时nextTick也支持Promise
export function nextTick(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;
if(useMacroTask) {
macroTimerFunc()
} else {
microTimerFunc()
}
}
if(!cb && typeof Promise !== 'undefined') {
return new Promise(resolve => {
_resolve = resolve
})
}
}