手动打造一个MVVM框架 TODO

seefly 2021年02月05日 202次浏览

手动打造一个MVVM框架

根据-github-刨析Vue实现原理

image-20210205095712649

一、核心原理简述

​ 利用Object.defineProperty()来劫持数据,当对某个属性进行update操作的时候,会触发它的一组Subscritber,并调用他们的update方法,这种方式就是典型的观察者模式。

1、Observer 观察者

​ 在vue源码里,它的角色就是观察者,通过Object.defineProperty来代理数据(现在是Proxy)。在数据更新的时候通知对应的订阅者,订阅者在收到提示之后做自己的业务逻辑,要么更新视图,要么更新其他数据,或者进行业务操作。

​ 这里比较厉害的是依赖收集,如何确定数据和订阅者之间的关系?按照最朴素的想法就是,我订阅者作为主动订阅的一方,那么肯定是主动向观察者发出申请,表明我对某个属性的变化感兴趣。观察者在收到申请之后将数据和订阅者关联起来,在数据变化时通知订阅者。很完美不是吗?这能够满足最基本的数据双向绑定,但是不要忘了,在Vue中数据和订阅者不是简单的 1:n 的关系,而是n:n的关系。 例如某个Computed计算属性A依赖data1data2,在他们任意一个发生变化的时候重新计算,给出计算后的结果。这是如何做到的?又或者是说Vue又是怎么知道计算属性A依赖data1data2的?通过语法分析解析你的表达式?这种方法可不可行我不知道,但Vue有更聪明的办法,那就是依赖收集

image-20210205103820731

​ 如上图所示,在订阅者调用Data1的时候,将全局变量-当前调用者(在Vue中是Dep.target)指向自己,然后去get数据,由于Data1Object.defineProperty()代理过,所以在其属性访问器get()内可以知道是谁在调用自己,并将其视为一个对自己的依赖,把它收集到自己的Registry中(在Vue中叫做Dep,意为依赖),这里说一下Registry,一个数据可以被多个订阅者订阅,一个订阅者也可以订阅多个数据。那么每个数据维护一个自己的订阅者列表就可以表达这种关系,这个订阅者列表就是Registry。然后,在数据被更新的时候,通知订阅者列表中的每个订阅者。这样一个闭环就完成了!

​ 这种方式从我们一开始想的主动订阅变成了被动收集,换一个角度就解决了如何确定依赖关系这种棘手的问题。