• vue3源码阅读-compiler-sfc


    vue-compiler-sfc主要是用来解析SFC组件,我们都知道,一个SFC(*.vue)文件三大要素是template、script、style,vue-compiler-sfc就是负责解析这三大要素。从源码src目录下,每个文件的命名大致就可以看出来各个文件的作用,我先从 compiler-sfc 的 index.ts 开始。

    (最近看源码深有感触的是,官文只是在说要怎么做,看了源码才知道为什么要这么做,并且还可以怎么做……,再就是测试用例真的很有用)

    index.ts 主要是导出了其他文件的功能。

    1.parse.ts:解析三大要素

    三大要素template、script、style的类型定义:

    想要看看具体解析后的sfc里面descriptor的结构,可以去运行vue-next/packages/compiler-sfc/__tests__ 下面个文件的测试用例。

    我们运行一个单测,看看parse script的结果:

    test('should expose top level declarations', () => {
        const script = compile(`
          <script setup>
          import { x } from './x'
          let a = 1
          const b = 2
          function c() {}
          class d {}
          </script>
          `)
        assertCode(script.content)
        console.log('----------------------')
        console.log(script)
        expect(script.content).toMatch('return { a, b, c, d, x }')
      })
    
    // 结果
    {
          type: 'script',
          // 可以看到,编译后的content,帮忙 return 了所有变量
          content: "import { x } from './x'
    " +
            '      
    ' +
            'export default {
    ' +
            '  expose: [],
    ' +
            '  setup(__props) {
    ' +
            '
    ' +
            '      let a = 1
    ' +
            '      const b = 2
    ' +
            '      function c() {}
    ' +
            '      class d {}
    ' +
            '      
    ' +
            'return { a, b, c, d, x }
    ' +
            '}
    ' +
            '
    ' +
            '}',
          loc: {
            source: '
    ' +
              "      import { x } from './x'
    " +
              '      let a = 1
    ' +
              '      const b = 2
    ' +
              '      function c() {}
    ' +
              '      class d {}
    ' +
              '      ',
            start: { column: 21, line: 2, offset: 21 },
            end: { column: 7, line: 8, offset: 131 }
          },
          attrs: { setup: true },
          setup: true,
          bindings: {
            x: 'setup-maybe-ref',
            a: 'setup-let',
            b: 'setup-const',
            c: 'setup-const',
            d: 'setup-const'
          },
          map: SourceMap {
            version: 3,
            file: null,
            sources: [ 'anonymous.vue' ],
            sourcesContent: [
              '
    ' +
                '      <script setup>
    ' +
                "      import { x } from './x'
    " +
                '      let a = 1
    ' +
                '      const b = 2
    ' +
                '      function c() {}
    ' +
                '      class d {}
    ' +
                '      </script>
    ' +
                '      '
            ],
            names: [],
            mappings: 'AAEM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC,CAAC,CAAC,CAAC,CAAC;;;;AAFe;AACpB,CAAC,CAAC,CAAC,CAAC,CAAC,CACC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACf,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC,CAAC,CAAC,CAAC,CAAC;;;;'
          },
          scriptAst: undefined,
          scriptSetupAst: [
            Node {
              type: 'ImportDeclaration',
              start: 7,
              end: 30,
              loc: [SourceLocation],
              range: undefined,
              leadingComments: undefined,
              trailingComments: undefined,
              innerComments: undefined,
              extra: undefined,
              specifiers: [Array],
              source: [Node]
            },
            Node {
              type: 'VariableDeclaration',
              start: 37,
              end: 46,
              loc: [SourceLocation],
              range: undefined,
              leadingComments: undefined,
              trailingComments: undefined,
              innerComments: undefined,
              extra: undefined,
              declarations: [Array],
              kind: 'let'
            },
            Node {
              type: 'VariableDeclaration',
              start: 53,
              end: 64,
              loc: [SourceLocation],
              range: undefined,
              leadingComments: undefined,
              trailingComments: undefined,
              innerComments: undefined,
              extra: undefined,
              declarations: [Array],
              kind: 'const'
            },
            Node {
              type: 'FunctionDeclaration',
              start: 71,
              end: 86,
              loc: [SourceLocation],
              range: undefined,
              leadingComments: undefined,
              trailingComments: undefined,
              innerComments: undefined,
              extra: undefined,
              id: [Node],
              generator: false,
              async: false,
              params: [],
              body: [Node]
            },
            Node {
              type: 'ClassDeclaration',
              start: 93,
              end: 103,
              loc: [SourceLocation],
              range: undefined,
              leadingComments: undefined,
              trailingComments: undefined,
              innerComments: undefined,
              extra: undefined,
              id: [Node],
              superClass: null,
              body: [Node]
            }
          ]
        }

    vue3的sfc的style模块多了一个 parseCssVars 的功能,支持在css中使用响应式的变量,用过v-bind去绑定。

    示例见:vue-next/packages/compiler-sfc/__tests__/cssVars.spec.ts

    2.compileStyle.ts 编译style模块

    vue3 内置了对各种css语法的预处理器,详情见:vue-next/packages/compiler-sfc/src/stylePreprocessors.ts,主要包括:

    export type PreprocessLang = 'less' | 'sass' | 'scss' | 'styl' | 'stylus'
  • 相关阅读:
    day1 instance,round,divmod,imput, 字符串
    Django中如何将javascript中的变量传给位于javascript内的{% url %}中的参数?
    demo_33 评论发布弹窗实现
    demo_32 富文本渲染
    demo_31 详情页面数据初始化
    demo_30 内容预加载
    demo_29 详情页页面展示
    demo_28 使用自定义事件同步数据
    demo_27 保存标签页数据
    demo_26 编辑标签页
  • 原文地址:https://www.cnblogs.com/catherinezyr/p/14544562.html
Copyright © 2020-2023  润新知