Vue2 简述组件编译全流程

394 阅读3分钟

Vue组件的编译

template编译流程

模板的介绍

  • 是什么:在vue中,模板指的是.vue文件中的<template>标签下的内容
  • 为什么:之所以要使用模板,是为了将html文件的内容组织到.vue中,方便代码管理
  • 怎么做:vue提供了与原生的html编写一致的体验,原生怎么写,模板就怎么写。

编译的介绍

  • 是什么:是一个功能,用来将.vue文件中的<template>下的内容,转换为渲染函数
  • 为什么:之所以要编译为渲染函数,是因为vue为了提高页面的渲染效率,采用了虚拟DOM技术。而渲染函数就是用来生成Vnode的工具函数。具体过程参考《Vue2 虚拟DOM理解》
  • 怎么做:将<template>下的内容作为字符串,然后设置一些固定的规则,通过状态机来循环解析所有的字符,生成一个固定模板的对象,具体过程参考《Vue框架的编译器》

script编译流程

脚本的介绍

  • 是什么:是vue中用来定义组件的逻辑的部分
  • 为什么:之所以要使用script,是为了在vue中实现与原生的js文件一样的功能
  • 怎么做:直接在<script>下编写js代码即可

编译过程

  • 观察vue2的源码中/packages/complier-sfc/src/compileScript.ts文件可知,主要调用complierScript函数来处理script中的内容,该函数接收两个参数,sfc,options,第一个是单文件组件的描述对象,第二个是编译选项
  • complierScript内的主要实现如下
    1. 采用babel将script下的内容进行一次转换,主要是进行一下语法的兼容
    2. 将转换前后的内容以及一些上下文整合为一个对象,然后返回。
    3. 返回的对象,结构如下
    {
        ...script,
        content,
        map,
        bindings,
        scriptAst: scriptAst.body
    }
    

style编译流程

样式的介绍

  • 是什么:是vue中用来定义template中的标签样式部分
  • 为什么:为了在vue中实现与.css文件相同的功能
  • 怎么做:直接在<style>下编写css即可

编译过程

  • 观察vue2源码中/packages/complier-sfc/src/compileStyle.ts文件可知,主要调用了doCompileStyle函数来处理style的内容,该函数接收一个参数,options,编译选项
  • doCompileStyle的主要内容如下
    1. 采用postcss来处理style的内容,主要是进行编译,优化,转换等
    2. 将转换前后内容以及一下上下文整合为一个对象,然后返回
    3. 返回的对象,结构如下
    {
        code: code || ``,
        map: outMap && outMap.toJSON(),
        errors,
        rawResult: result
    }
    

单文件组件的编译过程

  • 观察vue2源码中/packages/complier-sfc/parseComponent.ts文件可知,主要调用了parseComponent函数来处理sfc的内容,该函数主要接收两个参数,source,vue文件 options,编译选项
  • parseComponent的主要内容如下
    1. 调用函数分别来解析处理template,script,style三部分
    2. 将解析后的结果统一作为sfc对象的属性
    3. 返回的对象,结构如下
const sfc: SFCDescriptor = {
    source: string, //SFC源码字符串
    filename: string DEFAULT_FILENAME, //SFC文件名
    template: SFCBlock || null,  //SFC的template解析后的模块对象
    script: SFCScriptBlock || null,  //SFC的script解析后的模块对象
    scriptSetup: SFCScriptBlock || null, // TODO
    styles: SFCBlock|| [],  //SFC的style解析后的模块对象
    customBlocks: SFCCustomBlock || [],  //SFC的自定义块
    cssVars: string [],  //SFC的css变量数组
    errors: [],  //解析过程遇到的错误集合
    shouldForceReload: (prevImports: Record<string, ImportBinding>) => boolean 
    // 由complier-sfc设置,用来控制是否强制刷新
}