经过上三篇文章的分析,我们知道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函数
markStaticRoot
在上一步对所有的节点深度遍历并且做了静态标记之后,这一步要找出静态的根节点
这里只针对元素节点
当前节点为静态节点的条件
node.static为true 且 含有子节点 且 当子节点只有一个的时候该子节点非文本节点
一旦找到静态根节点就return 否则,就递归往下找到静态根节点
最后
这里的静态节点标记逻辑也非常简单,就是大量的条件判断加上递归处理。
目的就是为了能够加快节点对比的速度。
在节点优化之后,Vue将根据节点生成代码。这些代码就是生成虚拟dom的代码。Vue称之为codegen。