Vue.js 响应式系统内核剖析:Observe 机制揭秘
2024-03-01 10:42:00
在上一篇文章中,我们深入探究了 Vue.js 的声明、初始化和初始化状态机制。本篇将继续深入 Vue.js 的核心,揭开 Observe 机制的奥秘。Observe 是 Vue.js 响应式系统的重要组成部分,它负责侦听数据的变化并通知受影响的组件。
Observe 主要由两个部分组成:Dep(依赖项)和 Watcher(观察者)。我们从 Observe 的入口文件 src/core/observe/index.js
开始。
1. Dep:依赖项
Dep 用于收集和管理对数据项的依赖关系。它通过一个 subs
数组存储这些依赖项。当数据项发生变化时,Dep 负责通知所有已订阅的依赖项。
export class Dep {
constructor() {
this.subs = []
}
addSub(sub) {
this.subs.push(sub)
}
notify() {
this.subs.forEach(sub => sub.update())
}
}
2. Watcher:观察者
Watcher 负责观察数据项的变化并执行相应的回调函数。它包含一个 vm
(Vue 实例)、getter
(用于获取数据项)和 callback
(在数据项发生变化时执行的函数)。
export class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm
this.getter = expOrFn
this.callback = cb
}
update() {
this.run()
}
run() {
let value = this.get()
let oldVal = this.value
this.value = value
this.callback.call(this.vm, value, oldVal)
}
get() {
return this.getter.call(this.vm, this.vm)
}
}
3. Observe 入口
在 src/core/observe/index.js
中,提供了 Observe 入口函数 observe
。该函数根据传入数据的类型(对象、数组或响应式对象)进行不同的处理。
对于对象,它会遍历其所有属性并将其转换为响应式属性。对于数组,它会将数组包装为响应式数组。对于响应式对象,它会直接返回该对象。
export function observe(value) {
if (!isObject(value)) return value
let ob = new Observer(value)
if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
return value.__ob__
} else {
return ob
}
}
4. Observer:响应式对象
Observer 类是 Observe 的核心,负责将普通对象转换为响应式对象。它拥有一个 value
(原始数据)和一个 dep
(依赖项集合)。
当 Observer 被创建时,它会遍历 value
中的所有属性并将其转换为响应式属性。对于每个属性,它都会创建并添加一个 Dep 实例到属性上。
export class Observer {
constructor(value) {
this.value = value
this.dep = new Dep()
this.walk(value)
}
walk(obj) {
for (let key in obj) {
defineReactive(obj, key, obj[key])
}
}
}
5. defineReactive:定义响应式属性
defineReactive
函数负责将普通属性转换为响应式属性。它会创建一个 Dep 实例并将其与属性关联。当属性发生变化时,Dep 会通知所有订阅它的依赖项。
export function defineReactive(obj, key, val) {
const dep = new Dep()
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
get: function reactiveGetter() {
dep.depend()
return val
},
set: function reactiveSetter(newVal) {
const value = val
val = newVal
dep.notify()
},
})
}
总结
Vue.js 的 Observe 机制是一个复杂而精妙的系统。它通过 Dep 和 Watcher 的协作,实现了数据变化的侦听和响应。通过对源码的深入分析,我们可以更好地理解 Vue.js 响应式系统的强大功能。