携手创作,共同成长!这是我参与「掘金日新计划 · 8月更文挑战」的第12天,点击查看活动详情
什么是模板编译
vue把用户在<template></template>标签中写的类似html的内容进行编译,找出原生html的内容和非原生html的内容,经过一系列逻辑处理生成render函数,render会将这些内容生成对应的VNode,再通过patch过程得到要渲染视图中的VNode,然后根据VNode创建真实dom节点,插入视图中,完成视图的渲染更新。
因为有了模板编译,才有了虚拟DOM,才有了后续的视图更新
模板编译内部流程
1.把html代码转成ast语法树。(通过正则加循环,正则来匹配开始标签,结束标签,处理文本,以及标签名称。解析指令,class,style)
2.优化静态节点
3.根据ast生成render函数
// 源码位置: /src/complier/index.js
export const createCompiler = createCompilerCreator(function baseCompile (
template: string,
options: CompilerOptions
): CompiledResult {
// 模板解析阶段:用正则等方式解析 template 模板中的指令、class、style等数据,形成AST
const ast = parse(template.trim(), options)
if (options.optimize !== false) {
// 优化阶段:遍历AST,找出其中的静态节点,并打上标记;
optimize(ast, options)
}
// 代码生成阶段:将AST转换成渲染函数;
const code = generate(ast, options)
return {
ast,
render: code.render,
staticRenderFns: code.staticRenderFns
}
})
模版解析
// 代码位置:/src/complier/parser/index.js
/**
* Convert HTML string to AST.
*/
export function parse(template, options) {
// ...
parseHTML(template, {
warn,
expectHTML: options.expectHTML,
isUnaryTag: options.isUnaryTag,
canBeLeftOpenTag: options.canBeLeftOpenTag,
shouldDecodeNewlines: options.shouldDecodeNewlines,
shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
shouldKeepComment: options.comments,
start (tag, attrs, unary) {
},
end () {
},
chars (text: string) {
},
comment (text: string) {
}
})
return root
}
通过正则等方式将有效信息提取出来,将解析内容分为HTML解析器,文本解析器和过滤器解析器。
parse 函数就是解析器的主函数,在parse 函数内调用了parseHTML 函数,对模板字符串进行解析,在parseHTML 函数解析模板字符串的过程中,如果遇到文本信息,就会调用文本解析器parseText函数进行文本解析;如果遇到文本中包含过滤器,就会调用过滤器解析器parseFilters函数进行解析。