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、组件系统等更多复杂的功能。

相关推荐
我是伪码农3 小时前
Vue 1.23
前端·javascript·vue.js
wqwqweee3 小时前
Flutter for OpenHarmony 看书管理记录App实战:搜索功能实现
开发语言·javascript·python·flutter·harmonyos
HIT_Weston5 小时前
107、【Ubuntu】【Hugo】搭建私人博客:模糊搜索 Fuse.js(三)
linux·javascript·ubuntu
henujolly8 小时前
ethers.js读取合约信息
开发语言·javascript·区块链
毕设源码-郭学长9 小时前
【开题答辩全过程】以 基于Web的高校课程目标达成度系统设计与实现为例,包含答辩的问题和答案
前端
wuhen_n9 小时前
高阶函数与泛型函数的类型体操
前端·javascript·typescript
POLITE310 小时前
Leetcode 437. 路径总和 III (Day 16)JavaScript
javascript·算法·leetcode
難釋懷10 小时前
解决状态登录刷新问题
java·开发语言·javascript
ヤ鬧鬧o.10 小时前
多彩背景切换演示
前端·css·html·html5
一起养小猫10 小时前
Flutter实战:从零实现俄罗斯方块(三)交互控制与事件处理
javascript·flutter·交互