渲染层:虚拟DOM树

Vue是声明式渲染

在Vue2.0中,渲染层的实现做了根本性改动,那就是引入了虚拟DOM。

Vue的编译器在编译模板之后,会把这些模板编译成一个渲染函数。而函数被调用的时候就会渲染并且返回一个虚拟DOM的树。这个树非常轻量,它的职责就是描述当前界面所应处的状态。当我们有了这个虚拟的树之后,再交给一个patch函数,负责把这些虚拟DOM真正施加到真实的DOM上

在这个过程中,Vue有自身的响应式系统来侦测在渲染过程中所依赖到的数据来源。在渲染过程中,侦测到的数据来源之后,之后就可以精确感知数据源的变动。到时候就可以根据需要重新进行渲染。当重新进行渲染之后,会生成一个新的树,将新树与旧树进行对比,就可以最终得出应施加到真实DOM上的改动。最后再通过patch函数施加改动。

这样做的主要原因是,在浏览器当中,JavaScript的运算在现代的引擎中非常快,但DOM本身是非常缓慢的东西。当你调用原生DOM API的时候,浏览器需要在JavaScript引擎的语境下去接触原生的DOM的实现,这个过程有相当的性能损耗。所以,本质的考量是,要把耗费时间的操作尽量放在纯粹的计算中去做,保证最后计算出来的需要实际接触真实DOM的操作是最少的。

1.渲染函数

在Vue2.0里,用户可以选择直接跳过模板这一层去手写渲染函数,同时也有可选JSX支持。

在Vue2.0的路由和内部的一些实践上,都大量地应用渲染函数做复杂的抽象组件,比如过渡动画组件以及路由里面的link组件,都是用渲染函数实现的,同时还保留了它本身的依赖追踪系统。

2. 依赖追踪

通过ES5的 Object.defineProperty 方法实现

比如,我们给它一个原生对象,Vue会遍历这个数据对象的属性,然后进行属性转换。每一个属性会被转换为一个 getter 和一个 setter。同时每个组件会有一个对应的 watcher 对象,这个对象的职责就是在当前组件被渲染的时候,记录数据上面的哪些属性被用到了。

例如,在渲染函数里面用到A.B的时候,这个就会触发对应的 getter。整个渲染流程具体要点如下:

1. 当某个数据属性被用到时,触发 getter,这个属性就会被作为依赖被 watcher 记录下来。
2. 整个函数被渲染完的时候,每一个被用到的数据属性都会被记录。
3. 相应的数据变动时,例如给它一个新的值,就会触发 setter,通知数据对象对应数据有变化。
4. 此时会通知对应的组件,其数据依赖有所改动,需要重新渲染。
5. 对应的组件再次调动渲染函数,生成 Virtual DOM,实现 DOM 更新。

results matching ""

    No results matching ""