前言
使用 Vue 的时候,我们会用<template>...<template>来编写组件的 HTML 结构,<template>...<template>模板中的字符串会被编译成虚拟 DOM。
graph LR A[template 模板] --> B[虚拟 DOM]
Vue 有 2 个版本,一个是运行时 vue.runtime.min.js,可以创建 Vue 实例、渲染并处理虚拟 DOM,但是不能编译模板,另一个版本是完整版 vue.min.js,包含编译模板的功能。日常基于 Webpack、Vite 等的开发用到的都是运行时版本,模板编译是由相应的插件进行的。下面基于完整版的 Vue,调试 Vue 源码(见另一篇博客:调试 Vue 源码),看看总体的流程。
流程总览
举个栗子:
html- <script src="../../dist/vue.js"></script>
- <div id="demo"></div>
- <script type="text/x-template" id="template">
- <div>
- <div v-for="(item, index) in arr" @click="clickHandler">
- Current Value is {{ item }}
- </div>
- </div>
- </script>
- <script>
- const { ref } = Vue
- new Vue({
- name: 'Test',
- template: '#template',
- setup(props) {
- const arr = ref([1, 1, 4, 5, 1, 4])
- const clickHandler = () => {}
- return {
- arr, clickHandler
- }
- }
- }).$mount('#demo')
- </script>
这里使用完整版的 Vue,调用$mount方法时就开始进行模板解析,整合了各种配置之后,调用baseCompile开始模板编译:
graph LR Vue.prototype.$mount --> A[compileToFunctions] createCompilerCreator\nargs:baseCompile --> createCompiler -->A A --> baseCompile --> render
直接来看位于 /src/compiler/create-compiler.ts 的createCompilerCreator的核心代码:
ts- export function createCompilerCreator(baseCompile: Function): Function {
- return function createCompiler(baseOptions: CompilerOptions) {
- function compile(
- template: string,
- options?: CompilerOptions
- ): CompiledResult {
- const finalOptions = Object.create(baseOptions)
- // ... 合并配置的操作
- const compiled = baseCompile(template.trim(), finalOptions)
- return compiled
- }
- return {
- compile,
- compileToFunctions: createCompileToFunctionFn(compile)
- }
- }
- }
template是传入的模板字符串,compiled就是编译完的内容,实际上调用了传入的baseCompile进行编译。createCompileToFunctionFn中,做的主要是执行compile函数编译模板,以及返回编译后的render函数。核心代码在于baseCompile,在
src/compiler/index.ts。
ts- export const createCompiler = createCompilerCreator(function baseCompile(
- template: string,
- options: CompilerOptions
- ): CompiledResult {
- 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
- }
- })
parse负责把模板转化为ast抽象语法树,optimize对语法树进行优化(例如标记静态节点),generate则生成返回对应虚拟 DOM 的render函数。
也就是说,以下就是模板编译的大致流程:
graph LR template模板-->parse-->optimize-->generate-->render-->a[虚拟 DOM]
0 条评论未登录用户
Ctrl or + Enter 评论
