1.app.mount获取template
javascript
复制代码
const { mount } = app;
app.mount = (containerOrSelector: Element | ShadowRoot | string): any => {
const container = normalizeContainer(containerOrSelector);
if (!container) return;
const component = app._component;
if (
!isFunction(component) &&
!component.render &&
!component.template
) {
component.template = container.innerHTML;
// 2.x compat check
if (__COMPAT__ && __DEV__) {
...
// 省略非核心流程
...
}
}
// 这里获取template
container.innerHTML = "";
const proxy = mount(container, false, container instanceof SVGElement);
if (container instanceof Element) {
container.removeAttribute("v-cloak");
container.setAttribute("data-v-app", "");
}
return proxy;
};
return app;
2.compile
compile将传入的template编译成render函数,其实执行的是baseCompile
javascript
复制代码
export function compile(
template: string,
options: CompilerOptions = {}
): CodegenResult {
// 其实执行的是baseCompile
return baseCompile(
template,
extend({}, parserOptions, options, {
nodeTransforms: [
// ignore <script> and <tag>
// this is not put inside DOMNodeTransforms because that list is used
// by compiler-ssr to generate vnode fallback branches
ignoreSideEffectTags,
...DOMNodeTransforms,
...(options.nodeTransforms || []),
],
directiveTransforms: extend(
{},
DOMDirectiveTransforms,
options.directiveTransforms || {}
),
transformHoist: __BROWSER__ ? null : stringifyStatic,
})
);
}
3.通过parse获取AST
接着往下看baseCompile
javascript
复制代码
export function baseCompile(
template: string | RootNode,
options: CompilerOptions = {}
): CodegenResult {
...
// 获取AST
const ast = isString(template) ? baseParse(template, options) : template
const [nodeTransforms, directiveTransforms] =
getBaseTransformPreset(prefixIdentifiers)
...
}
4.transfom
解析AST中的属性,样式,指令等。完善抽象语法树
javascript
复制代码
export function baseCompile(
template: string | RootNode,
options: CompilerOptions = {}
): CodegenResult {
...
// 获取AST
const ast = isString(template) ? baseParse(template, options) : template
const [nodeTransforms, directiveTransforms] =
getBaseTransformPreset(prefixIdentifiers)
// 解析AST中的属性,样式,指令等。完善抽象语法树
transform(
ast,
extend({}, options, {
prefixIdentifiers,
nodeTransforms: [
...nodeTransforms,
...(options.nodeTransforms || []) // user transforms
],
directiveTransforms: extend(
{},
directiveTransforms,
options.directiveTransforms || {} // user transforms
)
})
)
// 最后一步通过generate生成渲染函数
return generate(
ast,
extend({}, options, {
prefixIdentifiers
})
)
}
5.generate
最后一步通过generate生成渲染函数。我们在test.html中写的template最终被编译成了成了下边的渲染函数被返回。
javascript
复制代码
return function render(_ctx, _cache) {
with (_ctx) {
const { toDisplayString: _toDisplayString } = _Vue
return _toDisplayString(msg)
}
}
6.总结
整个编译过程概括就是template=>ast=>transform=>ast=>generate=>render。这次我们已经基本了解整个编译过程。
作者:胖茶夫斯基
链接:juejin.cn/post/704659…
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。