我个人正在写Node.js的系列学习笔记node-learning-manual,包含了Node.js的基本模块和工程化相关的知识, 如果对你有帮助,请点个start,您的支持是对我最大的鼓励。
说到Vue框架大家可能已经很熟了,我从移动端转到前端两年多了,之前写过一些React的项目。最近在做Vue的项目,顺带研究一下Vue的底层代码。这系列文章中我会尝试回答一下以下四个问题:
- 当我们创建一个Vue.js实例时发生了什么?
- Vue模板是怎么编译为html代码?
- Vue的虚拟Dom到底有什么意义?
- 当属性改变模板是如何重新渲染的?
Template
Vue中的模板必须经过几个阶段才能传递给浏览器去渲染,首先我们写一个简单的模板
<div id="app">
<span v-if="dynamic">Dynamic text</span>
<span><p>Static text</p></span>
<button @click="toggleFlag">Toggle Dynamic</button>
</div>
复制代码
The compilation phase
Vue编译器读取一个组件的template,将会经过如下阶段:parsing, optimizing, codegen, render function, VNode。 最后生成的VNode将会由虚拟DOM处理来创建一个真实Dom。
Parsing stage
模板首先会被编译器编译成AST树, AST包含每个标签的信息类似:attribute, parent, children, tags, etc。自定义标签比如 v-for, v-if, v-once的会以key-value pair存在AST上。V-if指令经过编译将会推入attrsMap如 { v-if: "dynamic" }
Optimization stage
这一阶段目标主要是优化,检查AST树中哪些子树是完全静态,比如那些DOM永远不需要改变,将这些元素标记为静态元素。一旦子树被标识为静态,Vue将它们提升为常量,之后每一次重新渲染Vue也不需要创建新的Node给虚拟DOM。
CodeGen stage
在这个阶段一个真正的render function将会被创建,并在之后用于patch process。
根据静态表示,将函数分为简单渲染函数和静态渲染函数。最后渲染函数将被用于创建VNode当触发真正渲染进程。
注意,模板编译将会提前如果使用了类似构建过程。比如single file components。
The Patch process
Patch process是虚拟DOM与真实DOM交互的进程而已。 一个虚拟DOM只是一个JS对象代表一个Document Object Model。
Patch process所做的是处理旧的VNode与新的VNode,最终是将两者进行比较。
算法流程如下:
- 首先会检查Old VNode是否存在,如果不存在则创建一个。当APP第一次启动的时候,渲染函数初始化时Old VNode还没有存在。
- 接下来开始比较各个Node, 相同node保留在DOM,新的node将会加入,旧的不配合node将会从虚拟DOM删除,然后将改变真实的DOM
- 各个Node的style, class, dataset, event-listener也会做相应的改变。
我个人正在写Node.js的系列学习笔记node-learning-manual,包含了Node.js的基本模块和工程化相关的知识, 如果对你有帮助,请点个start,您的支持是对我最大的鼓励。