深入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源码也会后续更新出来,喜欢的点点关注。

相关内容

热门资讯

银行职工因贪污罪获刑后留任,在... 新京报记者 刘锦涵 制作 礼牧周 ▲新京报我们视频出品(ID:wevideo) 近日,农发行福建福鼎...
黄金创40年来最大单日跌幅!金... (来源:劳动报) 转自:劳动报 1月31日,国际金银价格同步大跌,创40余年来最大跌幅。国内金饰价...
“一人公司”近来何以兴起? 2026年开年,“一人公司”发展备受关注。这种新型创业模式正在上海、北京、江苏等地悄然兴起,凭借低成...
寒武纪预计 2025 年净利润... 消息,AI 芯片企业寒武纪今日发布 2025 年年度业绩预告: 经财务部门初步测算,公司预计 2...
和讯投顾徐剑波:ETF买入法! 这轮牛市是机构主导的ETF牛市,选对ETF往往比选股更加赚钱。那么如何投资ETF?今天教给大家一个非...
君乐宝上市申请已递交,国内乳品... 2026年 1月19日,中国领先的综合乳制品企业君乐宝乳业集团股份有限公司正式向香港联交所递交主板上...
大涨!马斯克,突传大消息!重磅... SpaceX的“赚钱能力”曝光。 据最新消息,世界首富埃隆·马斯克旗下的商业航天公司SpaceX去年...
原创 顶... 2025年微博之夜定档于2026年2月5日北京线上直播,这场已经走过二十多年风雨的互联网年度盛典,因...
体检查出肺结节?3个日常行为正... 太原龙城中医医院科普:如今越来越多人在体检中发现肺结节,看到报告上的“阴影”便忧心忡忡。其实研究表明...
记者观察丨美联储下任主席提名揭... 在经过长达一年反复挑选后,美国总统唐纳德·特朗普终于做出决定,提名凯文·沃什为下一任美联储主席,接替...
首饰金,一夜大跌上百元!金价暴... 【导读】多家首饰品牌金价出现大幅下跌 中国基金报记者 忆山 随着国际金价急速下跌,国内首饰金价也迎来...
原创 一... 一个亲自参观过我国稀土提炼工厂的日本人在社交平台发文,竟然毫不客气地指出,无论是日本还是美国,都几乎...
环球网财经系列专访 1月27日至28日,全国贸促工作会议暨中国贸促会第六届全国委员会第六次会议在京召开。 会议指出,“...
默茨警告:“大国世界”要来了,... 【文/观察者网 熊超然】当地时间1月29日,德国总理默茨在德国联邦议院发表其任内的第二次施政声明。在...
路透解析“马斯克集团”:Spa... SpaceX 凤凰网科技讯 北京时间1月31日,据路透社报道,长期以来,埃隆·马斯克(Elon Mu...
启动“二改” 永辉在京完成21... 北京商报讯(记者 赵述评 实习记者 毛思怡)1月31日,永辉超市北京龙湖长楹天街店经一个多月闭店调改...
《宜宾散装白酒连锁经营规范》团... 近日,由宜宾市酒类协会牵头归口、宜宾安宁酒厂主导起草,四川谊宾酒业、宜宾学院、劲牌南溪酒业等多家本地...
印度牙医博士打造全印首款人形机... 2026 年 1 月 23 日,印度浦那的 Muks Robotics 正式宣布,自主研发的社交人形...
金银价创新高,引发全球“贵金属... 【环球时报记者 倪浩 环球时报特约记者 甄翔】连日来,国际市场金银价格持续大涨。1月29日当天,亚太...
财经观察丨“爱你老己”背后的消... 新华网北京1月31日电岁末年初,一句“爱你老己,明天见”席卷社交网络,成为年轻人自我关怀的新表达。热...