vue:响应式原理解析,深入理解vue的响应式系统
Vue的响应式系统是如何工作的?
- 响应式对象的初始化:Vue在创建或更新data对象时,会使用
Observer
类来遍历对象的属性,并使每个属性变为响应式的,即每个属性都有一个Dep
(依赖)收集器,用于追踪它的所有订阅者(即Watcher)。 - 属性访问与依赖追踪:每当属性被访问时(例如模板渲染中),Vue会创建一个
Watcher
,并将其注册为该属性的依赖。 - 属性变更检测:当属性发生变更时,Vue会通过
Observer
类来检测变更,并通知对应的Dep
,Dep
再进一步通知所有依赖它的Watcher
,Watcher
接着会触发相关的更新流程(例如重新渲染组件)。 - 优化:Vue实现了一个高效的检查循环,称为“patch”过程,它能够智能地比对新旧虚拟节点之间的差异,并只应用必要的DOM改动。
以下是一个简化的响应式原理示例代码:
// 假设有一个简单的Vue实例
new Vue({
data: {
message: 'Hello Vue!'
},
template: `<div>{{ message }}</div>`
}).$mount('#app');
// 响应式系统的核心函数示例
function defineReactive(obj, key, val) {
const dep = new Dep(); // 创建一个依赖收集器
// 使用ES5的Object.defineProperty
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
dep.addSub(Dep.target); // 添加订阅者到依赖收集器
return val;
},
set: function reactiveSetter(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // 通知所有订阅者
}
});
}
// Watcher类示例
class Watcher {
constructor(vm, expOrFn, cb) {
Dep.target = this; // 设置当前Watcher为目标订阅者
this.cb = cb;
this.value = expOrFn(vm); // 触发属性访问,创建依赖
Dep.target = null; // 访问结束后清除目标订阅者
}
update() {
const oldValue = this.value;
this.value = this.get(); // 重新获取最新值,建立新的依赖
if (oldValue !== this.value) {
this.cb(this.value); // 值有变化时执行回调
}
}
get() {
// 触发属性访问,创建依赖
}
}
// 依赖收集器Dep的示例
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update()); // 通知所有订阅者执行更新
}
}
以上代码仅为响应式系统的简化示例,实际的Vue实现要复杂得多,包括响应式数组的处理、循环引用的处理、缓存优化等。
评论已关闭