Vue源码解析:模版编译之来龙去脉(一)
模版编译,Vue的有一大特点。我们在开发中常常会将看似html的代码都写在<template></template>标签中。说看似html代码,是因为在原生html中没有类似与v-if,v-for的一些指令。那么写在<template></template>中的代码片段为什么能被浏览器解析?说到底,还是要归功于Vue的模版编译。什么是模版编译?模版编
模版编译,Vue的有一大特点。我们在开发中常常会将看似html的代码都写在<template></template>标签中。说看似html代码,是因为在原生html中没有类似与v-if,v-for的一些指令。那么写在<template></template>中的代码片段为什么能被浏览器解析?说到底,还是要归功于Vue的模版编译。
什么是模版编译?
模版编译,就是把用户编写的类html代码将非原生代码和原生代码分离出来,经过一系列的逻辑处理,最终生成render函数的过程,就是Vue的模版编译。那这一些列的罗就处理是什么呢?且看下图:
具体来说就是将一堆模版字符串抽象成AST对象树,然后用AST树生成render函数。三个阶段:
- 模板解析阶段:将一堆模板字符串用正则等方式解析成抽象语法树
AST
; - 优化阶段:遍历
AST
,找出其中的静态节点,并打上标记; - 代码生成阶段:将
AST
转换成渲染函数;
// 源码位置: /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
}
})
- const ast =parse(template.trim(), options):
parse
会用正则等方式解析template
模板中的指令、class
、style
等数据,形成AST
。 - optimize(ast, options):
optimize
的主要作用是标记静态节点,这是Vue
在编译过程中的一处优化,在进行patch
的过程中,DOM-Diff
算法会直接跳过静态节点,从而减少了比较的过程,优化了patch
的性能。 - const code =generate(ast, options): 将
AST
转化成render
函数字符串的过程,得到结果是render
函数 的字符串以及staticRenderFns
字符串。
模版编译的流程是什么呢?
我们知道<template></template>编写的类html中包含了真正的html,以及一些标签属性,vue指令等,所以解析的流程总的来说应该是:HTML解析器是主线,先用HTML解析器进行解析整个模板,在解析过程中如果碰到文本内容,那就调用文本解析器来解析文本,如果碰到文本中包含过滤器那就调用过滤器解析器来解析。
// 代码位置:/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
}
这是vue实现的源码。parse
函数就是解析器的主函数,在parse
函数内调用了parseHTML
函数对模板字符串进行解析,在parseHTML
函数解析模板字符串的过程中,如果遇到文本信息,就会调用文本解析器parseText
函数进行文本解析;如果遇到文本中包含过滤器,就会调用过滤器解析器parseFilters
函数进行解析。
Vue整体的模版编译流程大致是这样,未完,待续。。。。
更多推荐
所有评论(0)