nextTick只是异步更新策略的一环,不能把1nextTick等同于异步更新
1.实现队列机制
当触发了watcher.update方法后,通过queueWatcher把触发的更新都存储在一个数组中,在nextTick异步函数的回调中遍历这些更新操作,依次执行,从而达到异步批量更新的逻辑。
update(){
queueWatcher(this);
}
import {
nextTick
} from '../util/next-tick'
let has = {};
let queue = [];
function flushSchedulerQueue() {
for (let i = 0; i < queue.length; i++) {
let watcher = queue[i];
watcher.run()
}
queue = [];
has = {}
}
let pending = false
export function queueWatcher(watcher) {
const id = watcher.id;
if (has[id] == null) {
has[id] = true;
queue.push(watcher);
if(!pending){
nextTick(flushSchedulerQueue)
pending = true;
}
}
}
2. nextTick实现原理
nextTick是一个根据兼容性不断降级的微任务或者宏任务,值的注意的是在它的内部也有一个数组用来存储回调函数,从而实现用户自己调用的nextTick能够访问到最新的dom
let callbacks = [];
function flushCallbacks() {
callbacks.forEach(cb => cb());
}
let timerFunc;
if (Promise) { // then方法是异步的
timerFunc = () => {
Promise.resolve().then(flushCallbacks)
}
}else if (MutationObserver) { // MutationObserver 也是一个异步方法
let observe = new MutationObserver(flushCallbacks); // H5的api
let textNode = document.createTextNode(1);
observe.observe(textNode, {
characterData: true
});
timerFunc = () => {
textNode.textContent = 2;
}
}else if (setImmediate) {
timerFunc = () => {
setImmediate(flushCallbacks)
}
}else{
timerFunc = () => {
setTimeout(flushCallbacks, 0);
}
}
export function nextTick(cb) {
callbacks.push(cb);
timerFunc();
}