我们首先来看vue2.x中的实现,为简单起见,我们这里不考虑多级嵌套,也不考虑数组
vue2.x中的实现
其本质是new Watcher(data, key, callback)
的方式,而在调用之前是先将data中的所有属性转化成可监听的对象, 其主要就是利用Object.defineProperty
,。
class Watcher{ constructor(data, key, cb){ } } //转换成可监听对象 function observe(data){ new Observer(data) } //修改数据的getter和setter function defineReactive(obj, key){ let value = obj[key]; Object.defineProperty(obj, key, { enumerable: true, configurable: true, get(){ return value; }, set(newVal){ value = newVal } }) }
Observer的实现很简单
class Observer { constructor(data){ this.walk(data); } walk(data){ for(var key in data) { // 这里不考虑嵌套的问题,否则的话需要递归调用walk defineReactive(data, key) } } }
现在怎么将watcher和getter/setter联系起来,vue的方法是添加一个依赖类:Dep
class Watcher{ constructor(data, key, cb){ this.cb = cb; Dep.target = this; //每次新建watcher的时候讲给target赋值,对target的管理这里简化了vue的实现 data[key];//调用getter,执行addSub, 将target传入对应的dep; vue的实现本质就是如此 } } class Dep { constructor(){ this.subs = []; } addSub(sub){ this.subs.push(sub); } notify(){ this.subs.forEach(sub => sub.cb()) } } function defineReactive(obj, key){ let value = obj[key]; let dep = new Dep(); //每一个属性都有一个对应的dep,作为闭包保存 Object.defineProperty(obj, key, { enumerable: true, configurable: true, get(){ dep.addSub(Dep.target) Dep.target = null; return value; }, set(newVal){ value = newVal dep.notify(); } }) }
以上就是vue的思路,vue3之所以要从新实现,主要有这几个原因:
- Object.defineProperty的性能开销。
- defineReactive一开始就要对要监听的对象所有属性都执行一遍,因为传统方法要将一个对象转换成可监听对象,只能如此。
- 添加删除属性的问题。
- 还有一点就是这个模块被耦合到了vue里面,新版本可以单独作为一个库来使用。
然后我们来看看同样的功能采用Proxy会怎样实现。
Proxy的实现
将一个对象转换成Proxy的方式很简单,只需要作为参数传给proxy即可;
class Watcher { constructor(proxy, key, cb) { this.cb = cb; Dep.target = this; this.value = proxy[key]; } } class Dep { constructor(){ this.subs = [] } addSub(sub){ this.subs.push(sub); } notify(newVal){ this.subs.forEach(sub => { sub.cb(newVal, sub.value); sub.value = newVal; }) } } const observe = (obj) => { const deps = {}; return new Proxy(obj, { get: function (target, key, receiver) { const dep = (deps[key] = deps[key] || new Dep); Dep.target && dep.addSub(Dep.target) Dep.target = null; return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { const dep = (deps[key] = deps[key] || new Dep); Promise.resolve().then(() => { dep.notify(value); }) return Reflect.set(target, key, value, receiver); } }); } var state = observe({x:0}) new Watcher(state, 'x', function(n, o){ console.log(n, o) }); new Watcher(state, 'y', function(n, o){ console.log(n, o) }); state.x = 3; state.y = 3;
也许一开始我们只关心x和y,那么就不会对其他的属性做相应的处理,除非添加watcher,其他时间target都是null
总结
以上所述是小编给大家介绍的Proxy可以优化vue的数据监听机制问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com
暂无评论...
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
2024年11月16日
2024年11月16日
- 罗大佑1982《之乎者也》无法盗版的青春套装版 [WAV+CUE][1G]
- 曾庆瑜1989-款款柔情[日本东芝版][WAV+CUE]
- Scelsi-IntegraledesquatuorsacordesetTrioacordes-QuatuorMolinari(2024)[24bit-WAV]
- 房东的猫2017-房东的猫[科文音像][WAV+CUE]
- 杨乃文.2016-离心力(引进版)【亚神音乐】【WAV+CUE】
- 群星.2024-珠帘玉幕影视原声带【TME】【FLAC分轨】
- 芝麻龙眼.2008-光阴隧道民歌记录3CD【乡城】【WAV+CUE】
- 谭艳《再度重相逢HQII》头版限量[低速原抓WAV+CUE][549M]
- ABC唱片《蔡琴三十周年纪念版》6N纯银镀膜 [WAV+CUE][1.1G]
- 海来阿木《西楼情歌》开盘母带[WAV+CUE][1.1G]
- TheGesualdoSix-QueenofHeartsLamentsandSongsofRegretforQueensTerrestrialandCele
- 王建杰2011-荣华富贵[喜玛拉雅][WAV+CUE]
- 孙悦2024-时光音乐会[金蜂][WAV+CUE]
- 秦宇子.2020-#YUZI【海蝶】【FLAC分轨】
- 苏有朋.1994-这般发生【华纳】【WAV+CUE】