vue 渲染原理

如今基本全部的框架都已经认同这个见解——DOM应尽量是一个函数式到状态的映射。状态便是惟一的真相,而DOM状态只是数据状态的一个映射。以下图所示,全部的逻辑尽量在状态的层面去进行,当状态改变的时候,View应该是在框架帮助下自动更新到合理的状态,而不是说当你观测到数据变化以后手动选择一个元素,再命令式地去改动它的属性。数组

 

下图是Vue的一个模板示例,若是没有用过Vue的话,能够大概感受到这是一个怎样的概念。浏览器

 

其实,在模板语法上,Vue跟Angular是比较类似。在Vue1.0里面,模板实现跟Angular相似,以下图所示,把模板直接作成在浏览器里面parse成DOM树,而后去遍历这个树,提取其中的各类绑定。架构

 

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

 

从架构来说,Vue2.0 依然是写同样的模板,(Vue2.0于前段时间发布,具体报道:更轻更快的Vue.js 2.0)。在最左边,Vue2.0跟1.0的模板语法绝大部分是兼容的。Vue的编译器在编译模板以后,会把这些模板编译成一个渲染函数。而函数被调用的时候就会渲染而且返回一个虚拟DOM的树。这个树很是轻量,它的职责就是描述当前界面所应处的状态。当咱们有了这个虚拟的树以后,再交给一个patch函数,负责把这些虚拟DOM真正施加到真实的DOM上。在这个过程当中,Vue有自身的响应式系统来侦测在渲染过程当中所依赖到的数据来源。在渲染过程当中,侦测到的数据来源以后,以后就能够精确感知数据源的变更。到时候就能够根据须要从新进行渲染。当从新进行渲染以后,会生成一个新的树,将新树与旧树进行对比,就能够最终得出应施加到真实DOM上的改动。最后再经过patch函数施加改动。函数

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

下面看渲染函数。用过React的开发者可能知道,React是没有模板的,直接就是一个渲染函数,它中间返回的就是一个虚拟DOM树。JSX实际就是一套用于让咱们更简单地去描述树状结构的语法糖。优化

以下图所示,在Vue2.0当中,能够看到就是说当好比左侧的模板,通过Vue的编译以后就会变成右侧的东西。动画

 

这个函数相似于建立一个虚拟元素的函数,咱们能够给它一个名字,给它描述应该有的属性特性和可能其余的数据。而后后面这个最后这个参数是个数组,包含了该虚拟元素的子元素。总的来讲2.0的编译器作的就是这个活。code

同时,在Vue2.0里,用户能够选择直接跳过模板这一层去手写渲染函数,同时也有可选JSX支持。从开发者的偏好以及开发者的效益的角度来考量,模板和JSX是各有利弊的东西。模板更贴近咱们的HTML,可让咱们更直观地思考语义结构,更好地结合CSS的书写。JSX和直接渲染函数,由于是真正的JavaScript,拥有这个语言自己的全部的能力,能够进行复杂的逻辑判断,进行选择性的返回最终要返回的DOM结构,可以实现一些在模板的语法限制下,很难作到的一些事情。对象

 

因此在Vue2.0里,两个都是能够选择的。在绝大部分状况下使用模板,可是在须要复杂逻辑的状况下,使用渲染函数。在Vue2.0的路由和内部的一些实践上,都大量地应用渲染函数作复杂的抽象组件,好比过渡动画组件以及路由里面的link组件,都是用渲染函数实现的,同时还保留了它自己的依赖追踪系统。

以下图所示,Vue的依赖追踪经过ES5的 Object.defineProperty 方法实现。好比,咱们给它一个原生对象,Vue会遍历这个数据对象的属性,而后进行属性转换。每个属性会被转换为一个 getter 和一个 setter。同时每一个组件会有一个对应的 watcher 对象,这个对象的职责就是在当前组件被渲染的时候,记录数据上面的哪些属性被用到了。

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

  • 当某个数据属性被用到时,触发 getter,这个属性就会被做为依赖被 watcher 记录下来。

  • 整个函数被渲染完的时候,每个被用到的数据属性都会被记录。

  • 相应的数据变更时,例如给它一个新的值,就会触发 setter,通知数据对象对应数据有变化。

  • 此时会通知对应的组件,其数据依赖有所改动,须要从新渲染。

  • 对应的组件再次调动渲染函数,生成 Virtual DOM,实现 DOM 更新。

这样一个流程跟主流的一些框架,例如React是有较大区别的。在React中,当组件复杂的时候须要用 shouldComponentUpdate 作优化。可是,它也有本身的各类坑,好比要确保该组件下面的组件不依赖外部的状态。虽然说这在大部分状况下是够用的,但遇到极大复杂度的应用,遇到性能瓶颈的时候,这个流程优化起来也是至关复杂的一个话题。

以下图所示,在Vue里面因为依赖追踪系统的存在,当任意数据变更的时,Vue的每个组件都精确地知道本身是否须要重绘,因此并不须要手动优化。用Vue渲染这些组件的时候,数据变了,对应的组件基本上去除了手动优化的必要性。

相关文章
相关标签/搜索