异步渲染
Vue可以响应数据变化,数据变化后会自动更新视图,如果每次修改都触发视图更新,会导致多次重复和不必要的渲染操作,例如一个组件使用了两个data的属性,更新两个属性如果触发两次渲染的话,会影响性能。因此Vue采取异步更新。
每次更新响应的属性之后,会将渲染的watcher放到一个队列中,在下个事件循环中再执行。
整个更新渲染的过程是:
- data的属性更新
- 通知依赖的render
- render的watcher加入队列(队列去重)
- nextTick清空watcher队列,执行各watcher中的回调
示例:
// 改变数据
vm.message = 'changed';
// 想要立即使用更新后的DOM。这样不行,因为设置message后DOM还没有更新
console.log(vm.$el.textContent); // 并不会得到'changed'
// nextTick里面的代码会在DOM更新后执行
Vue.nextTick(function(){
console.log(vm.$el.textContent) //可以得到'changed'
});
nextTick
在了解nextTick之前,需要先理解JavaScript的任务队列。
Vue.nextTick()方法用来设置让方法在下一个事件队列中执行。
Vue使用MutationObserver/Promise/setTimeout实现nextTick。Vue判断浏览器兼容性,按照MutationObserver -> Promise -> setTimeout的优先级实现nextTick。
Promise和setTimeout比较好理解,使用MutationObserver的目的是为了将回调加入到微任务队列,比宏任务队列更早执行。
我们知道,NodeJS中也有一个process.nextTick方法,也是用来设置回调异步,在下个循环中执行,但是这个方法并未将任务加入到宏任务队列或者微任务队列,它是将任务加到下次事件循环之前。详细的说明参考文章【5】。
参考文章
为何Vue采用异步渲染【2】