「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战」
Vue.js 源码分析 - parse
parse
解析器将模板解析为抽象语树 AST,只有将模板解析成 AST 后,才能基于它做优化或者生成代码字符串。
模板编译的过程 baseCompile
在学习 parse
函数之前,我们需要先了解是如何调用这个函数,何时调用的
这就需要我们先了解 baseCompile
函数了,baseCompile
是模板编译的核心函数,他一共做了三个事情 路径: src\compiler\index.js
- 调用
parse
:把模板转换成 ast 抽象语法树,然后优化抽象语法树 - 调用
generate
: 把抽象语法树生成字符串形式的 js 代码 - 返回一个包含以下数据内容的对象 :
ast
render
(渲染函数)(这里并不是render
函数,而是一个字符串形式的数据,需要toFunction
转换成函数形式)staticRenderFns
(静态渲染函数,生成静态)
parse 函数解析
- src\compiler\index.js
- 把模板转化成
ast
抽象语法树 - 抽象语法树,用来以树形的方式描述代码结构
const ast = parse(template.trim(), options) 复制代码
- 把模板转化成
- src\compiler\parser\index.js
parse() 复制代码
工具页面推荐
结构化指令的处理
- v-if 最终生成单元表达式
// src\compiler\parser\index.js
// structural directives
// 结构化的指令
// v-for
processFor(element)
processIf(element)
processOnce(element)
// src\compiler\codegen\index.js
export function genIf (
el: any,
state: CodegenState,
altGen?: Function,
altEmpty?: string
): string {
el.ifProcessed = true // avoid recursion
return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
}
// 最终调用 genIfConditions 生成三元表达式
复制代码
- v-if 最终编译的结果
ƒ anonymous(
) {
with(this){
return _c('div',{attrs:{"id":"app"}},[
_m(0),
_v(" "),
(msg)?_c('p',[_v(_s(msg))]):_e(),_v(" "),
_c('comp',{on:{"myclick":onMyClick}})
],1)
}
}
复制代码
v-if/v-for
结构化指令只能在编译阶段处理,如果我们要在render
函数处理条件或循环只能使用js 中的 if 和 for
Vue.component('comp', {
data: () {
return {
msg: 'my comp'
}
},
render (h) {
if (this.msg) {
return h('div', this.msg)
}
return h('div', 'bar')
}
})
复制代码
parse 函数总结
parse
函数在处理的过程中,会依次遍历模板字符串,把html
模板字符串转换为ast
对象,html
中的属性页指令都会被存储在ast
对应的属性上