Vue 模板编译入口

文章转自: https://www.jianshu.com/p/a635adc81709

写的挺好。

 

回忆之编译入口

编译,其实就是vue对模版指令和内置组件的处理

        编译我们最终执行的是compileToFunctions(template,options)。

        这个方法哪里来的?是从一个creatCompiler(baseOptions)方法返回对象中取到的(把该方法内的辅助方法作为参数结合一个外部引入的createCompileToFunctionFn方法得到的,该辅助方法会用到下面的编译核心方法baseCompile)。

        creatCompiler方法哪里来的?调用creatCompilerCreator(baseCompile)返会得到的。

        vue.js在不同平台下都会有编译的过程,因此编译过程中依赖的配置baseOptions会有所不同,像最近美团开源的mpvue是对小程序内的编译过程,也是基于vue编译实现的。

        vue.js利用函数柯里化的技巧很好的实现了baseOptions的参数保留。(我们第一次去拿到compileTofunctions时会把baseOptions做为参数传入createCompiler,之后在执行真正编译过程compileToFunctions中不会再传入baseOptions,实际上他利用函数柯里化的技巧把baseOptions通过闭包形成长久持有。函数createCompiler内引用了函数外的变量,并把持有该变量的函数compiled给return返回了,这样就形成了闭包,所以函数compile内对于baseOptions引用就会长久持有,之后你真正编译执行createCompileToFunctionFn方法中会调用compile方法,这时就不用再传入baseOptions配置)

        同样,vue.js也是利用函数柯里化技巧把baseCompile函数抽出来,把真正编译的过程和其他逻辑如对编译配置处理、缓存处理等剥离开。(编译核心方法baseCompile也是同理,把它做为参数传入,compile引用该函数并return 返回,形成闭包,使compile对baseCompile方法长久持有,之后你真正编译执行createCompileToFunctionFn方法中会调用compile方法,这时就不用再传入baseCompile方法)

具体代码描述:

这里creatCompiler已经得到creatCompilerCreator返回的函数creatCompiler,该返回函数传入参数baseOptions

creatCompilerCreator的定义

creatCompiler的定义,还没得到返回函数creatCompiler

createCompileToFunctionFn

编译概述:

            之前我们分析过模板到真实 DOM 渲染的过程,中间有一个环节是把模板编译成 render 函数,这个过程我们把它称作编译。

        虽然我们可以直接为组件编写 render 函数,但是编写 template 模板更加直观,也更符合我们的开发习惯。

        Vue.js 提供了 2 个版本,一个是 Runtime + Compiler 的,一个是 Runtime only 的,前者是包含编译代码的,可以把编译过程放在运行时做,后者是不包含编译代码的,需要借助 webpack 的 vue-loader事先把模板编译成 render函数。

        这一章我们就来分析编译的过程,对编译过程的了解会让我们对 Vue 的指令、内置组件等有更好的理解。不过由于编译的过程是一个相对复杂的过程,我们只要求理解整体的流程、输入和输出即可,对于细节我们不必抠太细。有些细节比如对于 slot 的处理我们可以在之后去分析插槽实现的时候再详细分析。

        当我们使用 Runtime + Compiler 的 Vue.js,它的入口是 src/platforms/web/entry-runtime-with-compiler.js,关于编译的入口就是在这里。

编译入口

        compileToFunctions 方法就是把模板 template 编译生成 render 以及 staticRenderFns,它的定义在 src/platforms/web/compiler/index.js 中:

compileToFunctions的定义

        可以看到 compileToFunctions 方法实际上是 createCompiler 方法的返回值,该方法接收一个编译配置参数,接下来我们来看一下 createCompiler 方法的定义,在 src/compiler/index.js 中:

createCompiler的定义

        createCompiler 方法实际上是通过调用 createCompilerCreator 方法返回的,该方法传入的参数是一个函数,真正的编译过程都在这个 baseCompile 函数里执行,那么 createCompilerCreator 又是什么呢,它的定义在 src/compiler/create-compiler.js 中:

createCompilerCreator的定义

        可以看到该方法返回了一个 createCompiler 的函数,它接收一个 baseOptions 的参数,返回的是一个对象,包括 compile 方法属性和 compileToFunctions 属性,这个 compileToFunctions 对应的就是 $mount 函数调用的 compileToFunctions 方法,它是调用 createCompileToFunctionFn 方法的返回值,我们接下来看一下 createCompileToFunctionFn 方法,它的定义在 src/compiler/to-function/js 中:

createCompileToFunctionFn定义

        compile 函数执行的逻辑是先处理配置参数,真正执行编译过程就一行代码:constcompiled=baseCompile(template,finalOptions)

        baseCompile 在执行 createCompilerCreator 方法时作为参数传入,如下:

baseCompil

所以编译的入口我们终于找到了,它主要就是执行了如下几个逻辑:

1、解析模板字符串生成 AST:cons tast=parse(template.trim(),options)

2、优化语法树:optimize(ast,options)

3、生成代码:const code=generate(ast,options)

总结

        编译入口逻辑之所以这么绕,是因为 Vue.js 在不同的平台下都会有编译的过程,因此编译过程中的依赖的配置 baseOptions 会有所不同。而编译过程会多次执行,但这同一个平台下每一次的编译过程配置又是相同的,为了不让这些配置在每次编译过程都通过参数传入,Vue.js 利用了函数柯里化的技巧很好的实现了 baseOptions 的参数保留。同样,Vue.js 也是利用函数柯里化技巧把基础的编译过程函数抽出来,通过 createCompilerCreator(baseCompile) 的方式把真正编译的过程和其它逻辑如对编译配置处理、缓存处理等剥离开,这样的设计还是非常巧妙的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值