vue源码复现

先进行语义解析各种vue命令生成模板语法树,再根据模板语法树使用createRender函数(render函数可使用自己定义的)创建render函数,在创建的同时使用闭包(函数柯里化)将模板语法树缓存起来,然后render函数结合data生成虚拟dom树,最后使用update方法根据diff规则将新的vnode替换旧的vnode(如果是相同id的新旧vnode比较,先遍历旧vnode所有属性,再遍历新vnode所有属性,然后进行属性补全)

 

vue2通过修改Array实例的__proto__重写了push等方法来实现数组的响应式

vue将this._data上的属性在做响应式处理时,在this上也放了一份,所以可以通过this也能访问到,其他的prop、methods也是同理

diff算法中自定义组件的更新和节点的更新判断逻辑不同

第一步先调用initdata对data里的每个属性对象做响应式处理在get方法中加上收集依赖(dep.depend)的方法,在set中添加派发更新(dep.notify)的方法,再调用mount解析template,触发渲染。这样的目的是将响应式和与渲染逻辑分开。

initdata中将数据做响应式处理,然后转交给initRender做渲染处理,通过52行使得每个响应式属性存储一份dep,每一份依赖又与该属性对应的的watch相关联,这样就使得渲染与属性分离

 

initRender做完抽象语法树转换后返回render函数,执行到16行的new Watch

 

 

进入到watcher后,又返回执行回调函数expOrFn,又返回至initRender中

 

 

 最终调用的是update方法渲染虚拟dom

 

三个属性收集了三个dep依赖

 

 

每个dep中包含要更新的watcher实例,对应着当前vue实例

 

 

这三个属性对应的都是同一watcher实例

 

 

①在initRender过程中,也就是在解析template的过程中会访问数据,此时会触发属性的get方法,

②通过dep.depend进行依赖收集,将vue实例保存至watcher中通过dep这个桥梁与该响应式属性相关联

③每次修改该属性,则触发dep.notify通知该属性绑定的watcher(对应的vue实例)进行重新渲染

④若template中没有用到该响应式属性(在data中定义的变量),则该属性也不会绑定任何watcher,即使修改了该属性的值,也不会进行渲染

 

 

posted @ 2022-08-15 00:04  姜小希  阅读(216)  评论(0编辑  收藏  举报