返回
Vue 2 数据响应式原理详解,揭开数据监听的奥秘
前端
2023-09-30 01:54:59
导言
Vue.js 作为一种流行的 JavaScript 框架,以其响应式数据管理而著称。在本文中,我们将深入探讨 Vue 2 的数据响应式原理,手把手地带你揭开数据监听的奥秘。
观察者模式与响应式
Vue 的响应式性是建立在观察者模式之上的。观察者模式是一种设计模式,允许对象(观察者)订阅其他对象(主题)的状态变化。当主题的状态发生变化时,它会通知所有订阅者,从而触发相应的动作。
在 Vue 中,数据对象扮演主题的角色,而 Vue 实例则扮演观察者的角色。当数据对象发生变化时,Vue 会自动检测到这些变化并触发更新视图。
数据劫持
为了实现响应式性,Vue 采用了一种名为数据劫持的技术。当 Vue 实例创建时,它会遍历数据对象并使用 getter 和 setter 来劫持对象的每个属性。
- getter: 当读取数据对象属性时,getter 会被调用。它返回属性的值,同时将 Vue 实例添加为该属性的依赖项。
- setter: 当写入数据对象属性时,setter 会被调用。它更新属性值,同时通知所有依赖项进行更新。
通过这种方式,Vue 可以跟踪数据对象属性的变化并相应地更新视图。
依赖收集
当数据对象属性被读取时,getter 会将 Vue 实例添加为该属性的依赖项。当属性发生变化时,setter 会通知所有依赖项进行更新。
Vue 使用依赖收集来优化更新过程。当属性发生变化时,只有与该属性相关联的组件和视图才会被更新,而不是整个应用程序。
手写简版 Vue 2 数据响应式
为了加深对 Vue 2 数据响应式原理的理解,我们来手动实现一个简版的 Vue 2 数据响应式。
数据劫持:
function observe(obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
defineReactive(obj, key, obj[key]);
}
}
}
function defineReactive(obj, key, value) {
let dep = new Dep();
Object.defineProperty(obj, key, {
get() {
dep.addSub(Dep.target);
return value;
},
set(newValue) {
if (newValue !== value) {
value = newValue;
dep.notify();
}
},
});
}
依赖收集:
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
Dep.target = null;
更新视图:
class Watcher {
constructor(vm, expr, cb) {
this.vm = vm;
this.expr = expr;
this.cb = cb;
this.value = this.get();
}
get() {
Dep.target = this;
const value = this.vm.data[this.expr];
Dep.target = null;
return value;
}
update() {
const newValue = this.get();
if (newValue !== this.value) {
this.value = newValue;
this.cb(newValue);
}
}
}
结语
通过深入剖析 Vue 2 的数据响应式原理,我们不仅掌握了其工作机制,更体会到观察者模式和数据劫持在实现响应式中的关键作用。理解这些原理对于编写高效且可维护的 Vue 应用程序至关重要。