vue 数据双向绑定原理代码
时间: 2023-02-19 19:14:08 浏览: 24
Vue 数据双向绑定的原理在于,它使用特定的数据监听机制,当数据发生变化时,就会触发相应的回调函数,从而实现数据的双向绑定。具体的实现代码如下:
Object.defineProperty(data, key, {
get() {
return value
},
set(newVal) {
if (value === newVal) {
return
}
value = newVal
// 执行回调函数,实现数据双向绑定
}
})
相关问题
vue2双向绑定的原理代码
Vue2 双向绑定的原理涉及到的代码比较多,涉及到 Vue 实例的初始化、数据劫持、依赖收集、更新等过程,下面是一个简化后的代码示例,仅供参考:
```javascript
// 定义一个 Observer 类,用于对数据对象进行劫持
class Observer {
constructor(data) {
this.data = data;
this.walk(data);
}
walk(data) {
Object.keys(data).forEach(key => {
this.defineReactive(data, key, data[key]);
});
}
defineReactive(data, key, value) {
const dep = new Dep();
Object.defineProperty(data, key, {
enumerable: true,
configurable: true,
get() {
dep.depend();
return value;
},
set(newValue) {
if (newValue === value) {
return;
}
value = newValue;
dep.notify();
}
});
}
}
// 定义一个 Watcher 类,用于进行依赖收集和更新 DOM 的操作
class Watcher {
constructor(vm, expOrFn, cb) {
this.vm = vm;
this.getter = parsePath(expOrFn);
this.cb = cb;
this.value = this.get();
}
get() {
Dep.target = this;
const value = this.getter.call(this.vm, this.vm);
Dep.target = null;
return value;
}
update() {
const oldValue = this.value;
this.value = this.get();
this.cb.call(this.vm, this.value, oldValue);
}
}
// 定义一个 Dep 类,用于存储 Watcher 对象并在数据变化时通知 Watcher 进行更新
class Dep {
constructor() {
this.subs = [];
}
depend() {
if (Dep.target) {
this.subs.push(Dep.target);
}
}
notify() {
this.subs.forEach(watcher => {
watcher.update();
});
}
}
Dep.target = null;
// 解析表达式路径
function parsePath(path) {
const segments = path.split('.');
return function(obj) {
for (let i = 0; i < segments.length; i++) {
if (!obj) return;
obj = obj[segments[i]];
}
return obj;
};
}
// 初始化 Vue 实例时进行数据劫持和依赖收集
function observe(value) {
if (!value || typeof value !== 'object') {
return;
}
return new Observer(value);
}
// 将 Vue 实例中的数据对象进行响应式处理
function defineReactive(obj, key, val) {
const dep = new Dep();
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get() {
dep.depend();
return val;
},
set(newValue) {
if (newValue === val) {
return;
}
val = newValue;
dep.notify();
}
});
}
// 创建 Vue 实例时进行数据初始化
class Vue {
constructor(options) {
this.$data = options.data;
observe(this.$data);
new Watcher(this, options.render, () => {
console.log('DOM updated');
});
}
}
// 使用示例
const vm = new Vue({
data: {
message: 'Hello, Vue!'
},
render() {
console.log('render');
}
});
vm.$data.message = 'Hello, World!'; // 触发 DOM 更新
```
上述代码仅为 Vue 双向绑定的原理代码示例,实际实现中还需要考虑更多的细节问题,例如模板编译、指令解析等。
简述 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!
阅读全文