vue源码分析(九) 编译之解析(parse)整体流程

10/9/2018 vue源码分析面试

# 1. 概述

​ 上一章 —— vue源码分析(八) 编译之整体流程 (opens new window) 我们分析了模板编译的入口以及整体逻辑,遗留了三个问题没有分析即编译生成 AST 树、AST 树优化、将 AST 编译成渲染函数,,本章节我们主要分析第一个问题——编译生成 AST 树。

# 2. 案例

​ 在分析之前我们以一个案例开始,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>parse</title>
  <script src="./vue.js"></script>
</head>
<body>
  <div id="app">{{ fullName }}</div>
    <script>
      new Vue({
        el: '#app',
        template: `
          <ul :class="classObject" class="list" v-show="isShow">
            <li v-for="(l, i) in list" :key="i" @click="clickItem(index)">{{ i }}:{{ l }}</li>
          </ul>
        `,
        data: {
          isShow: true,
          list: ['Vue', 'React', 'Angular'],
          classObject: {
            active: true,
            'text-danger': false
          }
        },
        methods: {
          clickItem(index) {
            console.log(index)
          }
        }
      })
    </script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 3.整体流程

parse 的定义,下面代码为精简后的伪代码。

​ 源码目录:src/compiler/parser/index.js

/**
 * Convert HTML string to AST.
 */
export function parse (
  template: string,
  options: CompilerOptions
): ASTElement | void {
  // ...
  getFnsAndConfigFromOptions(options)

  function warnOnce (msg, range) {
    // ...
  }

  function closeElement (element) {
    // ...
  }

  function trimEndingWhitespace (el) {
    // remove trailing whitespace node
    // ...
  }

  function checkRootConstraints (el) {
    // ...
  }

  parseHTML(template, {
    // options ...
    start (tag, attrs, unary, start, end) {
      // ...
      let element: ASTElement = createASTElement(tag, attrs, currentParent)
       // ...
      processElement(element)
      treeManagement()
      // ...
    },

    end (tag, start, end) {
      // ...
      treeManagement()
      closeElement(element)
    },

    chars (text: string, start: number, end: number) {
      // ...
      handleText()
      createChildrenASTOfText()
    },
    comment (text: string, start, end) {
      // ...
      createChildrenASTOfComment()
    }
  })
  return root
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

​ 这段代码主要做了两件事:

​ (1)、parseHTML : 函数的作用就是用来做词法分析的

​ (2)、parse : 函数的作用则是在词法分析的基础上做句法分析从而生成一棵 AST

# 4. parseHTML

说明:关于 parseHTML 我们会在下一章 (opens new window)做详细分析。

# 5. parse

说明:关于 parse 我们会在第十一章 (opens new window)做详细分析。

# 6.总结