vue2响应式--深度监听模拟
上篇优化了重复的监听,但当data数据为下图一个嵌套数据时,深层嵌套的属性没有响应效果。
import { observe } from "./observer";
import { Watcher } from "./watcher";
const data = {
test: "aa",
test1: "cc",
test2: {
dd: "aa",
},
};
const recursion = () => {
console.log(data.test2.dd);
};
observe(data);
new Watcher(recursion);
data.test2.dd = "as"; // 直接修改响应式没有触发
data.test2 = {
dd: "ss",
}; //整体赋值才有响应效果效果
我们发现整体赋值才可以有效果,我们就可以在数据劫持时判断当前的key值是否为对象类型,如果为对象类型就调用observe方法,对key值进行响应式。observer.js具体实现如下:
shallow属性设置数据是否需要深度监听,这样就可以深度监听了,但当我们重新对一个对象赋值后,再修改属性又没有响应效果,所以再set 方法里也添加一个深度监听方法。
import Dep from "./dep";
const NO_INIITIAL_VALUE = {};
function defineReactive(obj, key, val, shallow) {
// 获取当前属性有没有自定义方法;
let property = Object.getOwnPropertyDescriptor(obj, key);
// 判断当前属性有没有自定义get set 方法
let getter = property && property.get;
let setter = property && property.set;
// 没有val值,去obj里面的
if (
(!getter || setter) &&
(val === NO_INIITIAL_VALUE || arguments.length == 2)
) {
val = obj[key];
}
const dep = new Dep();
// 如果val值为对象类型,则深度监听
let childOb = !shallow && observe(val, false);
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function () {
//添加依赖函数
if (Dep.target) {
// dep.addSub(Dep.target);
dep.depend();
}
//如果有自定义方法则调用
let value = getter ? getter.call(obj) : val;
return value;
},
set: function (newVal) {
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
// 如果对一个对象整体赋值后,再修改对象属性也没有响应效果,在set也监听下
childOb = !shallow && observe(newVal, false);
//执行依赖当前属性的依赖函数
dep.notify();
},
});
}
export class Observer {
constructor(data, shallow = false) {
// shallow 属性判断是否需要深度监听
this.observer(data, shallow);
}
observer(data, shallow) {
let keys = Object.keys(data);
for (let key of keys) {
defineReactive(data, key, NO_INIITIAL_VALUE, shallow);
}
}
}
function observe(data, shallow = false) {
if (typeof data == "object") {
return new Observer(...arguments);
} else {
return false;
}
}
export { observe };
import { observe } from "./observer";
import { Watcher } from "./watcher";
const data = {
test: "aa",
test1: "cc",
test2: {
dd: "aa",
},
};
const recursion = () => {
console.log(data.test2.dd);
};
observe(data);
// 深度响应
new Watcher(recursion);
data.test2.dd = "as";
data.test2 = {
dd: "ss",
};
data.test2.dd = "111"; // 在set里添加深度监听

浙公网安备 33010602011771号