Vue-初始化和渲染过程

By
写代码

因为最近在用Vue,所以想把代码看一下,我觉得,越多的了解运行机制,越能更好的解决问题和……避坑。

本文必须提前要了解的两个概念是:defineProperty特性观察者模式

我们以一个简单的结构来开始

new Vue实际会进入Vue._init的初始化函数,这也是一切的开始。

初始化数据

这一步完成的工作是:为data创建Observer对象,使其产生响应式的效果。操作(get/setdata时,实际会操作挂载为_datadata,然后触发defineProperty设置的响应操作。

config.datavm.data

用一个proxy(vm, keys[i])完成对data内容的挂载。实现用代理(proxy)的方式访问

data创建对应的Observer

这一步操作之后,创建出的结构如下

Observer structure

Observer与data的对应结构

其中vmCount以该对象作为root $datavm计数器;dep实例包含一个自增Id,和一个Watcher列表以存储该依赖的改变会触发哪些watcher更新。

代码流程

逐层遍历对象的属性,生成与之对应的Observer,直到目标不为对象为止。childObdepdefineReactive时创建)一样,也作为闭包对象被reactiveGetter/reactiveSetter使用。

这一步结束后,会使data的所有属性都产生响应式的效果,即,操作(get/setdata里任意位置的数据,都会触发reactiveGetter/reactiveSetter

初次渲染

整个渲染过程都包在一个watcher里,并保存在实例对象的_watcher上。和watcher前后相连的,就是beforeMountmounted两个生命周期函数。(哪些操作或配置会创建Watcher?)

注意:watcher是包含value属性的,因为创建的时候就会执行传入的getter函数并获取返回值。所以声明在watch关键字里的函数要return一个返回值。

Watcher structure

需要关注的是这个watcher如何执行的。

依赖收集

这部分内容比较碎,涉及到两个类:DepWatcher。需要配合观察者模式来想一下整个流程。

Dep就是dependency(依赖),前面说过,一个data属性对应一个Observer,一个Observer里包含一个dep实例。dep.subs中存储了所有观察者(Watcher),属性变更,就会触发这些watcher

Watcher就是观察者,这里的watchervm._watcher是执行渲染的基本单元。对应depwatcher中也存储了dep实例和depId,即收集此渲染所需的依赖(dep,一个dep对应一个data属性)。

所以,整个过程就是围绕着这两个类来操作的:dep拿小本本记录所有在观察它的Watcher,当有变动是,让这些Watcher采取行动。Watcher也记录所有dep依赖,必要时(不再需要观察某个dep),通知dep把自己从它的小本本上划掉。

1、准备阶段
vm._watcher.get()。保存watcherDep的静态变量target,作为是否处于收集依赖阶段的标志位使用;

2、渲染阶段
Vue._render,在需要的时候(即调用到某个data属性时)获取data的值(逐层操作,直到取到目标值)

2.1 创建依赖列表
reactiveGetter外层闭包里的dep存入watchernewDepIdsnewDeps

2.2 创建反向记录
watcher存入闭包的dep.subs,这一步很重要,属性变更时,这里是入口;

3、重置阶段
Dep.target重新置为nullnewDepIds替换depIdsnewDeps替换deps,下次使用,如果检查上次有依赖A,如果此次没有,表示已经不需要(如v-iffalse),会从dep.subs中移除。

执行渲染

渲染会用到虚拟节点VNode,限于篇幅(其实还没看),这里先不说。大概看一下渲染流程,render会生成一个奇怪的代码段(template?),来实际执行从虚拟节点到DOM节点的渲染过程。

更新流程:复制旧的虚拟节点 => 更新内容 => 插入替换后的节点 => 删除之前的节点

后话:框架使用感受

坊间传言VueJS更易上手,ReactJS开发难度略高,AngularJS技能树陡峭。确实,和React相比,Vue似乎天然不要求组件化,这个感觉使前端开发更趋近于传统页面脚本的逻辑。产生这种感觉,除了先入为主,还有其本身特性比较……零碎,无论是watchcomputed或者更常用的directives,都在传达一个“霍,黑科技,这个窍门很NB”的感觉。

这种感觉乍一看很吸引人,因为新上手确实酷炫。但是带来的一个问题是,新手很容易忽略框架本身的特性。虽然Vue各个环节是完备的,但是最通常的使用,还是一个UI框架+一个大Vue实例,必要的时候使用几个第三方组件。甚至当感觉代码到一定规模觉得可以拆一下的时候,还是懒得动,或者觉得没必要。相比较来说,React只有stateprops,所以入门开发人员很容易聚焦到必要的代码结构和声明周期上来。

前面的唠叨和本文主旨没太大关系,因为完整对比是要放在对二者充分了解之后,这里只是从入门简单说两句。

0

Comments: 4

  1. 期待你出一个基于vue框架的wordpress主题,练练手,哈哈,另外,这vue确实在响应式和商品管理等操作上也更加高效灵活便捷,不错哈。

    08月20日
    • @郑永 主题倒是没问题。数据比较麻烦,需要使用rest-api插件,然后调用一堆不知道会不会有问题的接口。比较蛋疼

      @venmax 08月25日
  2. 所以wordpress团队用VueJS取代了ReactJS

    08月20日
    • @郑永 wp那个替换是技术无关的,因为react夹带问题专利条款

      @venmax 08月25日

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

:razz: