简述 vue双向绑定原理代码是如何实现的
时间: 2024-06-10 22:10:21 浏览: 103
详解vue的双向绑定原理及实现
Vue的双向绑定原理主要是通过数据劫持和发布订阅模式来实现的。
当创建Vue实例时,Vue会遍历data选项中的所有属性,使用Object.defineProperty方法将这些属性转换成getter和setter,并且在getter中收集依赖,在setter中触发依赖,从而实现对数据的监听。
当数据发生变化时,setter会通知订阅者更新视图,订阅者会重新渲染视图,从而实现数据的双向绑定。
以下是Vue双向绑定原理代码的简单实现:
// 数据劫持
function observe(obj) {
if (!obj || typeof obj !== 'object') {
return;
}
Object.keys(obj).forEach((key) => {
defineReactive(obj, key, obj[key]);
});
}
function defineReactive(obj, key, val) {
observe(val); // 递归子属性
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log(`get ${key}: ${val}`);
return val;
},
set: function reactiveSetter(newVal) {
console.log(`set ${key}: ${newVal}`);
val = newVal;
},
});
}
// 发布订阅模式
class Dep {
constructor() {
this.subs = []; // 存储所有的订阅者
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach((sub) => {
sub.update();
});
}
}
// 订阅者
class Watcher {
constructor(obj, key, cb) {
this.obj = obj;
this.key = key;
this.cb = cb;
Dep.target = this; // 将当前订阅者指向Dep静态属性target
this.value = obj[key]; // 触发getter,收集依赖
Dep.target = null;
}
update() {
const newVal = this.obj[this.key];
if (newVal !== this.value) {
this.value = newVal;
this.cb && this.cb(newVal);
}
}
}
// 测试代码
const vue = {
data: {
message: 'Hello, Vue!',
},
};
observe(vue.data);
new Watcher(vue.data, 'message', (newVal) => {
console.log(`watcher1: ${newVal}`);
});
new Watcher(vue.data, 'message', (newVal) => {
console.log(`watcher2: ${newVal}`);
});
vue.data.message = 'Hello, World!';
// 输出:
// get message: Hello, Vue!
// set message: Hello, World!
// watcher1: Hello, World!
// watcher2: Hello, World!
阅读全文