写文章不容易,点个赞呗兄弟
专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】
如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧
【Vue原理】Compile - 源码版 之 generate 节点拼接
终于走到了 Vue 渲染三巨头的最后一步了,那就是 generate,反正文章已经写完了,干脆早点发完,反正这部分内容大家也不会马上看哈哈
或者先看白话版好了
Compile - 白话版
然后,generate的作用就是,解析 parse 生成的 ast 节点,拼接成字符串,而这个字符串,是可以被转化成函数执行的。函数执行后,会生成对应的 Vnode
Vnode 就是Vue 页面的基础,我们就可以根据他完成DOM 的创建和更新了
比如这样
ast
{
tag:"div",
children:[],
attrsList:[{
name:111
}]
}
拼接成函数
"_c('div', { attrs:{ name:111 } }, [])"
转成函数
new Function(传入上面的字符串)
生成 Vnode
{
tag: "div",
data:{
attrs: {name: "111"}
},
children: undefined
}
本文概览
本文主要讲的是如果去把 生成好的 ast 拼接成 函数字符串(跟上面那个转换一样),而 ast 分为很多种,而每一种的拼接方式都不一样,我们会针对每一种方式来详细列出来
下面将会讲这么多种类型节点的拼接
静态节点,v-for 节点,v-if 节点,slot 节点,组件节点,子节点 等的拼接,内容较多却不复杂,甚至有点有趣
那我们就来看看 generate 本身的函数源码先
比较简短
function generate(ast, options) {
var state = new CodegenState(options);
var code = ast ? genElement(ast, state) : '_c("div")';
return {
render: "with(this){ return " + code + "}",
//专门用于存放静态根节点的
staticRenderFns: state.staticRenderFns
}
}
对上面出现的几个可能有点迷惑的东西解释一下
参数 options
options 是传入的一些判断函数或者指令函数,如下,不一一列举
{
expectHTML: true,
modules: modules$1,
directives: directives$1
....
};
函数 CodegenState
给该实例初始化编译的状态,下面会有源码
函数 genElement
把 ast 转成字符串的 罪魁祸首
generate 返回值
你也看到了
1 返回 genElement 拼接后的字符串code
这就是作为 render 的主要形态,包了一层 with
render 会有一块内容专门说,with 就不多说了哈,就是为了为 render 绑定实例为上下文
2 返回 静态根节点 的 静态render
这是一个 数组,因为一个模板里面可能存在多个静态根节点,那么就要把这些静态根节点都转换成 render 字符串保存起来,就是保存在数组中
上面是静态根节点?简单就是说,第一静态,第二某一部分静态节点的最大祖宗,如下图
两个 span 就是 静态根节点,他们都是他们那个静态部分的最大祖宗,而 div 下 有 v-if 的子节点,所以 div 不是静态根节点
然后下面这个静态模板,解析得到 render 放到 staticRenderFns 是这样的
<div name="a">
<span>111</span>
</div>
staticRenderFns=[
`
with(this){
return _c('div',
{attrs:{"name":"a"}},[111])]
)
}
`
]
而 staticRenderFns 也会在 render 模块下详细记录
CodegenState
初始化实例的编