vue 数据响应式原理 - 递归侦测对象的全部属性
- 官网的响应式原理图解:
- 三种框架的数据变化类型:
- Object.defineProperty() 方法:
- Object.defineReactive() 方法:
let obj = {};
function defineReactive(data, key, val) {
Object.defineProperty(data, key, {
// 可枚举
emuerable: true,
// 可以被配置,比如可以被 delete
configurable: true,
get() {
console.log(`正在访问obj的${key}属性`, val);
return val;
},
set(newValue) {
console.log(`正在改变obj的${key}属性`, newValue);
if (val === newValue) { return };
val = newValue;
}
})
}
defineReactive(obj, 'a', 10);
defineReactive(obj, 'b', 30);
obj.a = 30;
obj.a++;
obj.b = 66;
console.log(obj.a);
console.log(obj.b);
- 递归侦测对象全部属性
文件目录:
index.js
import observe from './observe';
let obj = {
a: {
m: {
n: {
e: {
f: 5
}
}
}
},
b: 3
};
observe(obj);
obj.a.m.n.e.f = 10;
observe.js
import Observer from './Observer.js';
// 创建 observe 函数,注意函数的名字没有r
export default function observe (value) {
// 函数只为对象服务
if (typeof value !== 'object') return;
// 定义 ob
let ob;
if (typeof value.__ob__ !== 'undefined') {
ob = value.__ob__;
} else {
ob = new Observer(value);
}
return ob;
}
Observer.js
import { def } from './utils.js';
import defineReactive from './defineReactive.js';
export default class Observer {
constructor(value) {
console.log('我是Observer的构造器', value);
// 给实例(构造函数中的this表示实例)添加了__ob__属性
def(value, '__ob__', this, false);
console.log('我是Observer构造器', value);
// Observer类的目的是:将一个正常的 object 转换为每个层级的属性都是响应式(可以被侦测的)的 object
this.walk(value);
}
// 遍历
walk(value) {
for (let key in value) {
defineReactive(value, key);
}
}
}
defineReactive.js
import observe from './observe';
export default function defineReactive(data, key, val) {
console.log('我是defineReactive', data, key);
if (arguments.length == 2) {
val = data[key];
}
// 子元素要进行 observe, 至此形成了递归,
// 这个递归不是函数自己调用自己
let childOb = observe(val);
Object.defineProperty(data, key, {
// 可枚举
emuerable: true,
// 可以被配置,比如可以被 delete
configurable: true,
get() {
console.log(`正在访问${key}属性`, val);
return val;
},
set(newValue) {
console.log(`正在改变${key}属性`, newValue);
if (val === newValue) { return };
val = newValue;
// 当设置了新值,新值也要 observe
childOb = observe(newValue);
}
})
}
utils.js
export const def = function(obj, key, value, emurable) {
Object.defineProperty(obj, key, {
value,
emurable,
writable: true,
configurable: true
})
}
生活是痛苦的白天,死亡是凉爽的夜晚。