Vue中双向数据绑定是如何实现的

Vue.js 的双向数据绑定是通过其响应式系统实现的。当 Vue 实例创建时,它会遍历 data 对象中的所有属性,并使用 Object.defineProperty 将它们转化为 getter/setter,使得 Vue 能够追踪每个属性的变化,并在变化时通知相关的依赖进行更新。

以下是 Vue.js 双向数据绑定的基本实现原理的简化版代码示例:

复制代码
复制代码
``function defineReactive(obj, key, val) {
// 创建一个唯一的 Dep 对象,用于存储该属性的所有依赖
const dep = new Dep();

// 获取属性的原始值
let value = val;

// 定义 getter
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
// 如果存在依赖,则添加该依赖到当前属性的 Dep 对象中
if (Dep.target) {
dep.addSub(Dep.target);
}
return value;
},
set: function reactiveSetter(newVal) {
// 当属性值发生变化时,通知所有依赖进行更新
if (newVal === value) return;
value = newVal;
dep.notify();
}
});
}

class Dep {
constructor() {
this.subs = [];
}

addSub(sub) {
this.subs.push(sub);
}

notify() {
this.subs.forEach(sub => sub.update());
}
}

// 用来存储当前的 Watcher 对象,在 getter 中使用
Dep.target = null;

class Watcher {
constructor(vm, expOrFn, cb) {
this.cb = cb;
this.vm = vm;
this.expOrFn = expOrFn;
this.value = this.get();
}

get() {
// 将当前的 Watcher 对象赋值给 Dep.target,以便在 getter 中添加依赖
Dep.target = this;
const value = this.vm[this.expOrFn];
// 执行完毕后,将 Dep.target 重置为 null
Dep.target = null;
return value;
}

update() {
this.run();
}

run() {
const value = this.get();
const oldVal = this.value;
if (value !== oldVal) {
this.value = value;
this.cb.call(this.vm, value, oldVal);
}
}
}

function observe(value, vm) {
if (!value || typeof value !== 'object') {
return;
}
let obj = Array.isArray(value) ? new Object(value) : value;
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key]);
});
}

function Vue(options) {
this.$data = options.data;
observe(this.$data, this);
new Watcher(this, 'message', function(value, oldValue) {
console.log(`message changed from ${oldValue} to ${value}`);
});
}

let vm = new Vue({
data: {
message: 'Hello, Vue!'
}
});

// 测试双向数据绑定
vm.message = 'Hello, World!'; // 控制台会打印出 "message changed from Hello, Vue! to Hello, World!"``

这个示例中,我们定义了一个 defineReactive 函数来将对象的属性转化为 getter/setter,Dep 类用于存储属性的依赖(即 Watcher 对象),Watcher 类用于观察数据的变化并在变化时执行回调函数。observe 函数用于遍历对象的所有属性并调用 defineReactive 进行转化。在 Vue 实例中,我们创建了一个 Watcher 对象来观察 message 属性的变化,并在其变化时打印出一条消息。最后,我们修改 vm.message 的值来测试双向数据绑定是否生效。

需要注意的是,这个示例仅仅是为了说明 Vue.js 双向数据绑定的基本原理,并没有包含 Vue.js 完整框架中的所有特性和优化。在实际的 Vue.js 框架中,还包括了模板编译、指令解析、虚拟 DOM、组件系统等更多复杂的功能。

相关推荐
RopenYuan17 分钟前
FastAPI -API Router的应用
前端·网络·python
走粥1 小时前
clsx和twMerge解决CSS类名冲突问题
前端·css
Purgatory0011 小时前
layui select重新渲染
前端·layui
weixin199701080162 小时前
《中国供应商商品详情页前端性能优化实战》
前端·性能优化
九皇叔叔2 小时前
003-SpringSecurity-Demo 统一响应类
java·javascript·spring·springsecurity
赵孝正4 小时前
学习的本质是一个工程闭环:从模仿到内化的四阶段方法论(附风电实战案例)
前端·数据库·学习
低代码布道师4 小时前
纯代码实战:MBA培训管理系统 (十四) ——用户管理(批量选择与批量删除)
javascript·nextjs
打瞌睡的朱尤4 小时前
建立vue项目
vue.js