编译
const { render, staticRenderFns } = compileToFunctions(template, {
shouldDecodeNewlines,
shouldDecodeNewlinesForHref,
delimiters: options.delimiters,
comments: options.comments
}, this)
options.render = render
options.staticRenderFns = staticRenderFns// `createCompilerCreator` allows creating compilers that use alternative
// parser/optimizer/codegen, e.g the SSR optimizing compiler.
// Here we just export a default compiler using the default parts.
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
}
})此编译过程中的依赖的配置 baseOptions 会有所不同。而编译过程会多次执行,但这同一个平台下每一次的编译过程配置又是相同的,为了不让这些配置在每次编译过程都通过参数传入,Vue.js 利用了函数柯里化的技巧很好的实现了 baseOptions 的参数保留。同样,Vue.js 也是利用函数柯里化技巧把基础的编译过程函数抽出来,通过 createCompilerCreator(baseCompile) 的方式把真正编译的过程和其它逻辑如对编译配置处理、缓存处理等剥离开,这样的设计还是非常巧妙的。
同一个组件,多个地方用,就会多次编译啊,不过会缓存结果,直接从缓存里拿即可
浏览器处理p标签之内的div 是直接提取出来, vue 跟他保持一致
parse
编译过程首先就是对模板做解析,生成 AST,它是一种抽象语法树,是对源代码的抽象语法结构的树状表现形式。
AST 元素节点总共有 3 种类型,type 为 1 表示是普通元素,为 2 表示是表达式,为 3 表示是纯文本。其实这里我觉得源码写的不够友好,这种是典型的魔术数字,如果转换成用常量表达会更利于源码阅读。
总结: parse 的目标是把 template 模板解析 ast 树,
整个parse 过程就是利用正则表达式顺序解析模板, 对不同的标签和节点有不同的处理过程,直到模板解析完毕。
optimize
markStatic(root) 标记静态节点 ,markStaticRoots(root, false) 标记静态根。
解析子节点是不是static 只要有一个不是的话就跳出
这个是对 if else 做个判断
总结:
optimize 的目标是通过标记静态根的方式, 优化重新渲染过程中对静态节点的处理逻辑
optimize的过程就是深度遍历这个ast 树, 先标记静态节点, 在标记静态根。
make static 就是为了后续 make static root make static root 会在渲染过程中生成一个静态子 tree,也就是给 vnode 标记 isStatic,这样在 patchVnode 过程中就可以判断并跳过子树的对比。
codegen
会进行三种情况的判断
实际上就是把 render 代码串通过 new Function 的方式转换成可执行的函数,赋值给 vm.options.render,这样当组件通过 vm._render 的时候,就会执行这个 render 函数。那么接下来我们就重点关注一下这个 render 代码串的生成过程。
总结: codegen 的目标是把 ast 树转换成代码字符串,就是render 函数代码。然后再通过 new Function 转换成 render 函数,render 函数会返回一个 VNode 树,然后再 patch 过程中生成 DOM 树渲染到页面
整个 codegen 过程就是深度遍历 ast 树根据不同条件生成不同代码的过程。
我们平时写的 .vue 文件的时候写是template, 这个编译是发生在webpack 编译阶段, vue-loader 负责编译的。
最后更新于
这有帮助吗?