Vue源码解析:模板编译optimize(四)

174 阅读2分钟

经过上三篇文章的分析,我们知道Vue通过正则表达式解析,将模板字符串解析成一棵AST节点树。

接下来,Vue对这棵树做了一点优化,即,静态节点标记。

在上篇文章中,提到了v-pre指令,从代码中可知,带有v-pre节点的子节点都被添加了plain属性,其值为true,即,el.platin = true

optimize

1. 获取isStaticKey,是一个函数,用以判断ast节点的属性是包含在staticKeys内

2. isPlatformReservedTag,在浏览器平台,就是是否为H5标签

3. markStatic对每个ast树的每个节点进行静态节点标记

4. 根据markStatic的结果来找出静态的根节点

整个函数最终的目的是找出静态根节点,然后在节点对比更新的时候,跳过静态节点及其子节点,提升更新的效率。否则当节点数很多的时候,如果每个节点都进行对比,很消耗性能。

markStatic

深度遍历ast树,对每个节点都进行静态标记,为下一步做准备

1. 对当前节点用isStatic判断是否为静态节点

2. 逻辑判断,是否有必要进行递归处理,标记子节点

递归终止条件

非H5元素 且 非slot标签 且 inline-template属性值 为 null/undefined

对slot标签的说明:

1. 为了在组件更新的时候,一定更新插槽内容

2. 为了静态插槽内容可以hot-reloading

isStatic

静态节点的符合条件:

1. 非表达式节点

2. 文本节点

3. 不含v-bind/v-if/v-for属性 且 非slot component标签 且 非带v-for指令的template标签的子节点 且 节点的所有属性都包含在 staticKey内部的节点

isStatickey函数

判断ast节点的所有属性名是否在type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap, staticStyle, staticClass范围内

markStaticRoot

在上一步对所有的节点深度遍历并且做了静态标记之后,这一步要找出静态的根节点

这里只针对元素节点

当前节点为静态节点的条件

node.static为true 且 含有子节点 且 当子节点只有一个的时候该子节点非文本节点

一旦找到静态根节点就return 否则,就递归往下找到静态根节点

最后

这里的静态节点标记逻辑也非常简单,就是大量的条件判断加上递归处理。

目的就是为了能够加快节点对比的速度。

在节点优化之后,Vue将根据节点生成代码。这些代码就是生成虚拟dom的代码。Vue称之为codegen。