引言:
前面核心篇说过Vue 运行时的核心主要包括数据初始化、数据更新、异步队列、DOM渲染这几个部分,理解异步队列是理解数据更新非常重要的一部分,本文讲一下Vue的异步队列的思路以及实现原理,顺带讲一下 Vue 的 $nextTick。
一、Vue的异步队列是什么?
//从前面的分析我们知道,Vue 初始化后一般会创建不止一个 watcher ,包括渲染watcher 、computed 、watch中为每个属性创建的 watcher
Vue 中当侦听到数据变化进行更新时,对应的 watcher 并不会被直接执行,而是会被放入一个队列中在下一个事件循环中执行,并且执行的过程是一个异步执行,这个队列就是异步队列。
二、异步队列实现原理
Vue的异步队列是在数据更新时开启的,那么从数据更新的逻辑开始看
1 /** 2 * Define a reactive property on an Object. 3 */ 4 function defineReactive$$1 ( 5 obj, 6 key, 7 val, 8 customSetter, 9 shallow 10 ) { 11 var dep = new Dep(); 12 13 var property = Object.getOwnPropertyDescriptor(obj, key); 14 if (property && property.configurable === false) { 15 return 16 } 17 18 // cater for pre-defined getter/setters 19 var getter = property && property.get; 20 var setter = property && property.set; 21 if ((!getter || setter) && arguments.length === 2) { 22 val = obj[key]; 23 } 24 25 var childOb = !shallow && observe(val); 26 Object.defineProperty(obj, key, { 27 enumerable: true, 28 configurable: true, 29 get: function reactiveGetter () { 30 var value = getter ? getter.call(obj) : val; 31 if (Dep.target) { 32 dep.depend(); 33 if (childOb) { 34 childOb.dep.depend(); 35 if (Array.isArray(value)) { 36 dependArray(value); 37 } 38 } 39 } 40 return value 41 }, 42 set: function reactiveSetter (newVal) { 43 var value = getter ? getter.call(obj) : val; 44 /* eslint-disable no-self-compare */ 45 if (newVal === value || (newVal !== newVal && value !== value)) { 46 return 47 } 48 /* eslint-enable no-self-compare */ 49 if (customSetter) { 50 customSetter(); 51 } 52 // #7981: for accessor properties without setter 53 if (getter && !setter) { return } 54 if (setter) { 55 setter.call(obj, newVal); 56 } else { 57 val = newVal; 58 } 59 childOb = !shallow && observe(newVal); 60 dep.notify(); 61 } 62 }); 63 }
Dep.prototype.notify = function notify () { // stabilize the subscriber list first var subs = this.subs.slice(); if (!config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they fire in correct // order subs.sort(function (a, b) { return a.id - b.id; }); } for (var i = 0, l = subs.length; i < l; i++) { subs[i].update(); //watcher.update() } };
可以看到 当 数据发生变化时会通过调用