- 核心使用 defineProperty 实现数据的获取与修改监听 (get/set), Vue3使用了Proxy
- 使用闭包原理 把形参 val 转换成了内部私有变量, 便于set(修改)后,get(获取)能拿到最新修改的值
- 而数据本身可能会有多个属性,为了使用上不至于每次都手动调用 defineReactive 故封装了observe函数
- observe函数通过遍历,可以自动的将每个属性做劫持处理,并添加了非对象情况的过滤处理
- 数据本身可能存在多层级结构,所以defineReactive函数每次在调用时,都做了一次observe递归,以便子层级数据能被劫持到
- Vue.set || this.$set 实现就更简单了,添加额外的属性时,只需按defineReactive的格式手动添加即可,Vue便于使用封装了set函数,并挂载到了Vue原型上
function defineReactive(obj, key, val) {
observe(val)
Object.defineProperty(obj, key, {
get() {
console.log('get', key);
return val
},
set(v) {
if (val !== v) {
console.log('set', key);
observe(v)
val = v
}
},
})
}
function observe(obj) {
if (typeof obj !== 'object' || obj == null) {
return obj
}
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
function set(obj, key, val) {
defineReactive(obj, key, val)
}
const obj = {
foo: 'foo',
bar: 'bar',
baz: {
a: 1
}
}
observe(obj)