1.watcher更新的改写

1
2
3
4
5
6
7
8
9
10
11
export default class Watcher {
update() {
// 每次watcher进行更新的时候 是否可以让他们先缓存起来 之后再一起调用
// 异步队列机制
queueWatcher(this);
}
run() {
// 真正的触发更新
this.get();
}
}

在update更新方法中加入异步队列的机制


2.queueWatcher实现队列机制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let queue = [];
let has = {};
function flushSchedulerQueue() {
for (let index = 0; index < queue.length; index++) {
// 调用watcher的run方法 执行真正的更新操作
queue[index].run();
}
// 执行完之后清空队列
queue = [];
has = {};
}

// 实现异步队列机制
export function queueWatcher(watcher) {
const id = watcher.id;
// watcher去重
if (has[id] === undefined) {
// 同步代码执行 把全部的watcher都放到队列里面去
queue.push(watcher);
has[id] = true;
// 进行异步调用
nextTick(flushSchedulerQueue);
}
}

同步把watcher都放队列里面去,执行完队列的事件之后再清空队列,主要使用nextTick来执行watcher队列


3.nextTick实现原理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//通过MutationObserver监听DOM变化,异步方法
const observer = new MutationObserver(flushCallbacks);
const textNode = document.createTextNode(String(counter));
//通过promise
const p = Promise.resolve();
timerFunc = () => {
p.then(flushCallbacks);
};
//使用setImmediate
timerFunc = () => {
setImmediate(flushCallbacks);
};
//最后是setTimeout
timerFunc = () => {
setTimeout(flushCallbacks, 0);
};

微任务优先的方式调用异步方法执行nextTick包装的方法


4.$nextTick挂载原型

1
2
3
4
export function renderMixin(Vue) {
// 挂载在原型的nextTick方法 可供用户手动调用
Vue.prototype.$nextTick = nextTick;
}

最后把$nextTick挂载到Vue的原型