# Observe
- 处理响应式
- 通过
Object.defineProperty递归处理vm._data对象的属性。数组则通过修改原型链的方法来实现发布订阅。 - 通过defineReactive来为每个属性创建
dep,触发gettter的时候依赖收集,触发setter时,通过dep.notify(),调用dep.subs中所有watcher.update()去做更新操作。
export function observe (value: any, asRootData?: boolean) {
// 非对象和 Vnode 不做处理
if (!isObject(value) || value instanceof VNode) return
let ob: Obsever | void
// 如果已经创建了 wathcer 则直接返回
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
ob = value.__ob__
} else if {
ob = new Observer(value)
}
if (asRootData && ob) {
ob.vmCount++
}
return ob
}
# Observer
export class Observer {
value: any,
dep: Dep,
vmCount: number
constructor (value: any) {
this.value = value
this.dep = new Dep()
def(value, '__ob__', this)
if (Array.isArray(value)) {
// 修改数组原型链的方法
// ...
} else {
// 如果是对象则为每个属性设置响应式
this.walk(value)
}
}
// 为每个key绑定响应式
walk (obj: Object) {
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
defineReactive(obj, keys[i])
}
}
}
# defineReactive
export function defineReactive (
obj: Object,
key: string,
val: any,
customSetter?: Function,
shallow?: boolean
) {
const dep = new Dep()
// 获取 obj[key] 的属性描述符,如果是不可配置对象 直接 return
const property = Object.getOwnPropertyDesciptor(obj.key)
if (property && property.configurable === false) return
// 处理 computed 的 get 与 set
const getter = property && property.get
const setter = property && property.set
// 普通对象的情况下值为 obj[key]
if ((!getter || setter) && arguments.length === 2) {
val = obj[key]
}
// 递归
let childOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
// 拦截读取操作
get: function reactiveGetter () {
// data 中的值只会有 dep 不会有 wathcer,因为 data 中的值不依赖任何值,所以不需要创建 watcher
const value = getter ? getter.call(obj) : val
/**
* Dep.target 保存了当前正在触发 get() 的 Watcher
* 如果存在 Dep.target 说明有 watcher 被创建且引用了当前值(依赖当前值)
* 不存在 Dep.target 就代表正常的使用 则不需要依赖收集
*/
if (Dep.target) {
// 依赖收集。 Dep.target.addDep(this)
// addDep 会调用添加的 dep.addSub 在将 wathcer 添加到 dep.subs 中。
dep.depend()
if (childOb) {
childOb.dep.depend()
}
}
return value
},
set: function reactiveSetter (newVal) {
const oldVal = getter ? getter.call(obj) : val
// 如果 newVal 与 oldVal 值一样则不触发更新
if (newVal === oldVal || (newVal !== newVal && oldVal !== oldVal)) return
// 不存在 setter 说明是只读属性 直接 return
if (getter && !setter) return
if (setter) {
setter.call(obj, newVal)
} else {
val = newVal
}
// 新值也是响应式
childob = !shallow && observe(newVal)
// 更新依赖
dep.notify()
}
})
}