$nextTick的原理其实就是Js执行机制的问题,即微任务和宏任务那套东西。
同步视图更新:每次属性值改变,渲染函数的watcher会重新求值完成重新渲染,所以多个属性值修改会导致对此重新渲染。
异步视图更新:将执行更新操作的watcher放进一个队列中,并通过id避免重复放入,然后当所有突变完成后,再一次性执行队列里的观察者的更新方法,同时清空队列。
所以再wacther对象的update方法里,可以看到:
update () {
/* istanbul ignore else */
if (this.computed) {
// 省略...
} else if (this.sync) {
this.run()
} else {
queueWatcher(this)
}}
queueWatcher函数做的就是:
1、首先判断进来的watcher是否已有,没有就标记一下它的id是true;
2、当队列没有执行update时,就把新来的watcher丢到队列尾部,如果正在更新,就插入队列,保证执行顺序;
3、执行nextTick(flushSchedulerQueue)。
nextTick如何实现
Vue里的$nextTick其实就是对nextTick(fn, this)函数的封装。js的事件循环是在调用栈里拿一次宏任务执行,然后再对对应的微任务对应执行完毕,再去执行下一次宏任务。宏任务之间可能会穿插UI重渲染,所以最