今天记录下vue源码的响应式的源码学习,第一步,我们想下,为什么为们写一个data。然后里边的数据变化就能映射到dom的变化上。这里用到了Object.defineProperty(obj,key, {}),如果你还不了解建议去jsmdn上仔细了解下,这个函数的目的就是检测你得赋值和取值的过程用来定义自己的行为,比如obj[key]会拿到配置里边的get函数定义,obj[key] = 'xxx'会调用配置中的set。那么vue也是一样的,在get中做了依赖收集(也就是说哪些dom用到了我定义的这个key,然后记录下来,等执行set时候对记录下来的dom进行更新)。那我们了解了基本流程之后现在来看下vue的源码具体分析吧。对data的分析是来自_init -> initState -> initData
这里我们拿到我们穿进去的data,这里的这个data如果是一个函数的话那就调用取出来最后得到的是一个对象,箭头指的proxy函数的目的是把data中的各个key代理到vm实例上。这个时候我们就在单文件组件中用this[key]来取到对应的值。大家感兴趣的可以自己去看,如果有疑问的可以留言,大家一起讨论下。
重点来了。箭头指的observe函数,我们看下这个函数做了什么。
我们先把各个判断的逻辑省略掉,先看主体流程,我们这个时候new Observer(data)。这个Observe做了什么呐?
这里,我们首先new Dep()这个用来干什么呐?个人认为他是一个观察者模式,在这里我们会存储我们的依赖,即哪些dom模块订阅了我们的data,然后我们通过def这个函数把data.__ob__这个属性的值为当前的Ovserver实例。然后我们来执行walk(),默认为对象了,数组会在之后进行新的随笔来介绍。
walk的逻辑很简单,就是循环遍历我们的data。然后调用defineReactive方法。defineReactive中我们开始用我们上边讲到的Object.definePropery。
Dep.target:这个东西我们先理解为一个函数,这个函数的作用呐,就是更新dom的函数。还记得之前对于dep的定义吗?那么我们下面看看dep.depend()。这个方法。
这里又调用了Dep.target.addDep这个方法。
大家可以看到这个时候呐。我们把Dep.target保存到我们的dep中了。以后当我们数据发生变化,我们只要在dep的subs中依次调用就好了。这个文章可能不是很详细的介绍,值提供了一定的思路,大家自己研究扩展,如果有意可以一起交流学习。
备注:读慕课网黄亦老师的开源电子书进行整理的。