vue的object数据侦测
程序员文章站
2022-06-25 11:30:12
vue中把vm.$data作为一个object进行侦测...
vue中把vm.$data作为一个object进行侦测(Observe类),一个对象对应一个observe实例,监测里面的每一个属性值。但是由于js的限制,不能监测如下内容:
- 利用索引直接设置一个数组项
- 修改数组的长度
- 对象属性的添加或删除
在Observe类中,遍历所有属性
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
在defineReactive(obj,key[i])中为每一个属性生成一个依赖管理器(Dep类)
const dep = new Dep() //实例化一个依赖管理器,生成一个依赖管理数组dep
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get(){
dep.depend() // 在getter中收集依赖
return val;
},
set(newVal){
if(val === newVal){
return
}
val = newVal;
dep.notify() // 在setter中通知依赖更新
}
})
其中:
Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。在上面的方法中写了get和set方法。
在Watcher类里,访问每一个属性时,会把本Watcher实例加入到dep数组中,当某一个vm$data里的属性更新时,会执行Observe实例的set方法,执行dep.notify()方法,遍历该属性的所有依赖Watcher实例,执行实例的updete()方法,然后更新对应的视图。
export default class Watcher {
constructor (vm,expOrFn,cb) {
this.vm = vm;
this.cb = cb;
this.getter = parsePath(expOrFn)
this.value = this.get()
}
get () {
window.target = this;
const vm = this.vm
let value = this.getter.call(vm, vm)
window.target = undefined;
return value
}
update () {
const oldValue = this.value
this.value = this.get()
this.cb.call(this.vm, this.value, oldValue)
}
}
get()方法把实例化的Watcher赋给全局变量window.target,然后在调用数据的Observe中的get()方法,然后通过dev的depend()方法把本实例放入dev数组中。
depend () {
if (window.target) {
this.addSub(window.target)
}
}
本文地址:https://blog.csdn.net/qq_44953868/article/details/109577754
上一篇: 十进制转格雷码