深入vue2.0源码系列:依赖追踪与计算属性的实现
创始人
2025-05-30 03:11:00
0

前言

在 Vue.js 中,数据与视图之间的绑定是通过依赖追踪和计算属性来实现的。本文将深入学习 Vue.js 2.0 源码中依赖追踪和计算属性的实现原理。

依赖追踪

在 Vue.js 中,依赖追踪是实现响应式的核心。当一个响应式对象被访问时,Vue.js 会自动追踪这个对象的依赖关系,并将这些依赖关系建立成一个依赖图。当这个响应式对象的值发生改变时,Vue.js 会遍历这个依赖图,通知所有依赖于这个对象的地方更新视图。

Vue.js 中的依赖追踪是通过 Dep 类来实现的。每个响应式对象都对应一个 Dep 对象,它维护了这个响应式对象的所有依赖关系。

具体来说,当一个响应式对象被访问时,会触发它的 getter 函数。在 getter 函数中,会调用 Dep.targetaddDep 方法,将当前正在计算的计算属性或者渲染 Watcher 添加到这个响应式对象的 Dep 对象的依赖列表中。Dep.target 就是一个全局唯一的 Watcher,它代表当前正在计算的计算属性或者正在渲染的组件的 Watcher。这样就完成了依赖关系的建立。

下面是 Dep 类的简化实现:

class Dep {constructor() {this.subs = []; // 存储依赖于该响应式对象的所有 Watcher}depend() {if (Dep.target) {Dep.target.addDep(this); // 将当前正在计算的 Watcher 添加到依赖列表中}}notify() {for (let i = 0; i < this.subs.length; i++) {this.subs[i].update(); // 通知依赖于该响应式对象的所有 Watcher 更新视图}}addSub(sub) {this.subs.push(sub);}
}Dep.target = null;

上述代码中的 depend 方法用于在 getter 函数中添加依赖关系,notify 方法用于在响应式对象发生改变时通知所有依赖该对象的 Watcher 更新视图。而 addSub 方法则用于添加依赖于该响应式对象的 Watcher。

计算属性

计算属性是 Vue.js 中的一个重要特性,它允许开发者声明式地计算出一个值,并在模板中使用计算属性是通过 Watcher 类来实现的。每个计算属性都对应一个 Watcher 对象,它会自动追踪计算属性的依赖关系,并在依赖的数据发生改变时重新计算值并更新视图。

具体来说,当一个计算属性被访问时,会触发它的 getter 函数。在 getter 函数中,会调用 Dep.targetpushTarget 方法,将当前计算属性的 Watcher 设置为全局唯一的 Dep.target。这样,在计算属性的计算过程中,如果访问了响应式数据,就会触发这些响应式数据的 getter 函数,并将当前计算属性的 Watcher 添加到它们的 Dep 对象的依赖列表中。

当计算属性的依赖数据发生改变时,会触发这些数据对应的 Dep 对象的 notify 方法,通知所有依赖于这些数据的 Watcher 更新视图。而这些 Watcher 中,因为计算属性的 Watcher 也被添加到了它们的依赖列表中,所以也会被通知到。这样,计算属性的值就会重新计算,并更新视图。

下面是 Watcher 类的简化实现:

class Watcher {constructor(vm, expOrFn, cb) {this.vm = vm;this.getter = expOrFn;this.cb = cb;this.deps = [];this.depIds = new Set();this.value = this.get();}get() {Dep.target = this; // 将当前 Watcher 设置为全局唯一的 Dep.targetconst value = this.getter.call(this.vm); // 触发计算属性的 getter 函数,建立依赖关系Dep.target = null; // 恢复全局唯一的 Dep.targetreturn value;}update() {const oldValue = this.value;this.value = this.get(); // 重新计算计算属性的值this.cb.call(this.vm, this.value, oldValue); // 更新视图}addDep(dep) {const id = dep.id;if (!this.depIds.has(id)) {this.deps.push(dep); // 将依赖于该响应式对象的 Watcher 添加到该响应式对象的依赖列表中this.depIds.add(id);dep.addSub(this); // 将该 Watcher 添加到该响应式对象的依赖列表中}}
}

上述代码中的 addDep 方法用于在计算属性的 getter 函数中添加依赖关系,并将该计算属性的 Watcher 添加到依赖的响应式对象的 Dep 对象的依赖列表中。
了解这些原理可以帮助我们更好地理解 Vue.js 的响应式系统,并能更深入地理解计算属性和依赖追踪的机制。同时,我们也可以通过修改 Watcher 的实现方式,实现自定义的响应式行为。

下面是一个简单的例子,展示如何使用 Watcher 自定义响应式行为:

class CustomWatcher extends Watcher {constructor(vm, expOrFn, cb) {super(vm, expOrFn, cb);this.update(); // 在创建 CustomWatcher 时,先手动更新一次视图}update() {const oldValue = this.value;this.value = this.get(); // 调用父类的 get 方法计算新值this.cb.call(this.vm, this.value, oldValue); // 触发回调函数}
}

上述代码中的 CustomWatcher 类继承自 Watcher 类,并重写了 update 方法,将原来的更新视图的逻辑替换成了触发回调函数的逻辑。这样,在创建 CustomWatcher 时,只需要传入计算新值的函数和回调函数,就可以实现自定义的响应式行为。

总结

总结来说,依赖追踪和计算属性是 Vue.js 响应式系统的核心机制。通过依赖追踪,Vue.js 能够自动建立响应式数据之间的依赖关系,并在数据发生改变时自动更新视图。而计算属性则能够让我们将复杂的数据计算逻辑封装起来,以便更好地组织和复用代码。理解这些机制可以帮助我们更好地使用 Vue.js,同时也能够启发我们设计自己的响应式系统。

后续会继续更新vue2.0其他源码系列,包括目前在学习vue3.0源码也会后续更新出来,喜欢的点点关注。

相关内容

热门资讯

阿联酋最大银行及另两家中东银行... 观点网讯:5月8日,路透社报道指,阿联酋最大银行第一阿布扎比银行(First Abu Dhabi B...
深圳239亿地王易主,再造万象... 2017年,世茂集团豪掷239.43亿元拿下世茂深港国际中心地块,曾规划建筑高度达700米的深圳第一...
蔚来在安庆成立新能源科技公司 ... 天眼查App显示,近日,安庆蔚来新能源科技有限公司成立,法定代表人为姚蒀,注册资本500万人民币,经...
美国牛肉商期盼峰会重启对华出口 据路透社5月8日报道,美国牛肉生产商正期待特朗普与中国于5月14日至15日的峰会推动对华出口许可恢复...
创业板首家未盈利企业,市值突破... 5月8日,大普微总市值正式突破2000亿元大关。截至午间收盘,大普微涨14.07%,报493.1元/...
招商证券:董事长霍达因工作变动... 招商证券公告,公司董事长霍达因工作变动申请辞去董事长、执行董事等全部职务,辞任自辞呈送达董事会之日生...
原创 中... 【阅读须知】本文所引用的所有信息和数据,均为作者通过查阅官方资料与网络公开数据整理、分析而成,旨在为...
原创 从... 2026年5月5日,中国商务部发布了一项具有划时代意义的专项阻断禁令,这份公告让一向倚仗长臂管辖的美...
布米普特拉北京投资基金管理有限... 美国圣路易斯联邦储备银行总裁穆萨莱姆周三发出明确信号,美联储货币政策面临的潜在风险正在发生关键转向。...
加工的秘密:超精加工设备如何做... 你知道吗? 一根头发丝的直径大约0.07毫米,也就是70微米。 超精加工设备,可切出表面,其尺寸为0...
招商证券董事长霍达因工作变动离... 北京商报讯(记者 刘宇阳 实习生 王思奕)5月8日,招商证券发布关于公司董事长离任暨推举董事代行董事...
华帝股份营收创近3年新低,37... 乐居财经李兰近日,华帝股份(002035.SZ)发布2025年年度报告。 2025年,华帝股份实现营...
大模型融资杀疯了!月之暗面狂揽... 图源:视觉中国 5月7日,据华峰资本官微消息,国内头部大模型公司月之暗面(Kimi)于近日完成新一轮...
扎根长宁二十余载,仲利国际融资... 作为总部扎根上海长宁的优质台资金融企业,仲利国际融资租赁有限公司深耕融资租赁行业二十余载,始终坚守金...
估值210亿!李彦宏又将收获一... 来源:直通IPO,文/王非 国产GPU上市潮仍然汹涌,继两家登陆A股、两家登陆H股后,这家公司正推进...
基金“盲盒”拆了 公募基金正在迎来一场让投资者“看得懂”的变革。 近日,华夏、易方达、南方、招商等12家头部及特色基金...
原创 2... 前言 十年间,中国企业在印尼镍产业链累计砸下超过140亿美元,电厂、公路、码头和全套生产线,硬生生...
原创 欧... 俄罗斯卫星通讯社5月6日报道,欧盟宣布禁止欧洲银行为含有来自不可靠供应商的关键部件的可再生能源项目提...
原创 余... 2026年5月2日,在中国理财市场扎根十三年的余额宝,终于触碰到了一个让所有人错愕的数字——7日年化...
银华基金增聘谭普景共同管理银华... 来源:新浪基金∞工作室 5月8日,银华基金管理股份有限公司发布公告称,为银华中证机器人交易型开放式指...