Vue监听数据对象变化源码

2020-06-16 06:26:53易采站长站整理

Observer

简单说过 Object.defineProperty 之后,就要开始扯 Observer 了。observer,中文解释为“观察者”,观察什么东西呢?观察对象属性值的变化。故此,所谓 observer,就是给对象的所有属性加上 getter、setter,如果对象的属性还有属性,比如说 {a: {a: {a: ‘a’}}},则通过递归给其属性的属性也加上 getter、setter:


function Observer(value) {
this.value = value;
this.walk(value);
}
Observer.prototype.walk = function(obj) {
var keys = Object.keys(obj);
for(var i = 0; i < keys.length; i++) {
// 给所有属性添加 getter、setter
defineReactive(obj, keys[i], obj[keys[i]]);
}
};

var dep = [];

function defineReactive(obj, key, val) {
// 有自定义的 property,则用自定义的 property
var property = Object.getOwnPropertyDescriptor(obj, key);
if(property && property.configurable === false) {
return;
}

var getter = property && property.get;
var setter = property && property.set;

// 递归的方式实现给属性的属性添加 getter、setter
var childOb = observe(val);
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function() {
var value = getter ? getter.call(obj) : val;
dep.push(value);
return value;
},
set: function(newVal) {
var value = getter ? getter.call(obj) : val;
// set 值与原值相同,则不更新
if(newVal === value) {
return;
}
if(setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
// 给新赋值的属性值的属性添加 getter、setter
childOb = observe(newVal);
console.log(dep);
}
});
}

function observe(value) {
if(!value || typeof value !== 'object') {
return;
}
return new Observer(value);
}

Watcher

Observer 通过设置数据对象的 getter、setter 来达到监听数据变化的目的。数据被获取,被设置、被修改,都能监听到,且能做出相应的动作。

现在还有一个问题就是,谁让你监听的?

这个发出指令的就是 Watcher,只有 Watcher 获取数据才触发相应的操作;同样,修改数据时,也只执行 Watcher 相关操作。

那如何讲 Observer、Watcher 两者关联起来呢?全局变量!这个全局变量,只有 Watcher 才做修改,Observer 只是读取判断,根据这个全局变量的值不同而判断是否 Watcher 对数据进行读取,这个全局变量可以附加在 dep 上:

dep.target = null;

根据以上所述,简单整理下,代码如下:


function Watcher(data, exp, cb) {
this.data = data;
this.exp = exp;