行文介绍
本文主要介绍 vue 中 template compile 的主体思路和源码流程。
适合想要梳理模板编译对应的源码函数调用流程的童鞋。为大家滤清思路。
具体的分析请查看文末参考链接。
主体思路
三步走:
- 将模板解析为 AST。
parse
。parse 使用正则等方式解析 template 模板中的指令,class,style 等数据,形成 AST - 优化 AST。
optimize
。主要作用是标记 static 静态节点,后面当 update 更新界面时,会有 diff 的过程,会直接跳过静态节点,从而减少比较过程,优化 patch 性能。 - 将 AST 转换为
render
函数。generate。将 AST 转换为 render function 字符串,得到结果是 render 字符串以及 staticRenderFns 字符串。
源码函数调用流程
整个源码非常贴近函数式编程,但是也导致阅读理解的成本很高,基本都是高阶函数,函数被传入传出的,很容易被绕晕。
但是抓住核心就行,createCompiler
函数。
核心函数
createCompiler
简要流程
compileToFunctions
<==
createCompiler
<==
createCompilerCreator
<==
createCompileToFunctionFn
<==
createFunction
详细流程
// src/platforms/web/entry-runtime-with-compiler.js
const {render, staticRenderFns} = compileToFunctions(template, {
outputSourceRange: process.env.NODE_ENV !== 'production',
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
// src/platforms/web/compiler/index.js
const {compile, compileToFunctions} = createCompiler(baseOptions)
// src/compiler/index.js
export const createCompiler = createCompilerCreator(function baseCompile (
template: string,
options: CompilerOptions
): CompiledResult {
// 三步走 parse optimize generate
const ast = parse(template.trim(), options)
if (options.optimize !== false) {optimize(ast, options)
}
const code = generate(ast, options)
return {
ast,
render: code.render,
staticRenderFns: code.staticRenderFns
}
})
// src/compiler/create-compiler.js
export function createCompilerCreator (baseCompile: Function): Function {return function createCompiler (baseOptions: CompilerOptions) {
function compile (
template: string,
options?: CompilerOptions
): CompiledResult {const compiled = baseCompile(template.trim(), finalOptions)
...
return compiled
}
return {
compile,
// 真实使用的是这个函数 compileToFunctions
compileToFunctions: createCompileToFunctionFn(compile)
}
}
}
// src/compiler/to-function.js
export function createCompileToFunctionFn (compile: Function): Function {
return function compileToFunctions (
template: string,
options?: CompilerOptions,
vm?: Component
): CompiledFunctionResult {
// compile
const compiled = compile(template, options)
res.render = createFunction(compiled.render, fnGenErrors)
return (cache[key] = res)
}
}
// src/compiler/to-function.js
function createFunction (code, errors) {
try {return new Function(code)
} catch (err) {errors.push({ err, code})
return noop
}
}
参考链接
https://github.com/answershut…【这篇文章不错,推荐阅读】