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

相关推荐
真滴book理喻4 分钟前
Vue(四)
前端·javascript·vue.js
蜜獾云6 分钟前
npm淘宝镜像
前端·npm·node.js
dz88i86 分钟前
修改npm镜像源
前端·npm·node.js
Jiaberrr10 分钟前
解锁 GitBook 的奥秘:从入门到精通之旅
前端·gitbook
程序员_三木28 分钟前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
顾平安1 小时前
Promise/A+ 规范 - 中文版本
前端
聚名网1 小时前
域名和服务器是什么?域名和服务器是什么关系?
服务器·前端
桃园码工1 小时前
4-Gin HTML 模板渲染 --[Gin 框架入门精讲与实战案例]
前端·html·gin·模板渲染
沈剑心2 小时前
如何在鸿蒙系统上实现「沉浸式」页面?
前端·harmonyos
一棵开花的树,枝芽无限靠近你2 小时前
【PPTist】组件结构设计、主题切换
前端·笔记·学习·编辑器