【vue高频面试题—基础篇】:template到render的过程

57 阅读3分钟

在 Vue.js 中,模板 (template) 会被转换成渲染函数 (render function),从而生成虚拟 DOM (Virtual DOM)。这个过程包括以下几个关键步骤:


1. 模板编译 (Template Compilation)

当使用 Vue 的模板语法(<template>)时,模板会被编译为 JavaScript 渲染函数。这一步的具体过程如下:

  1. 解析模板 (Parsing)
    Vue 的编译器会将 HTML 模板解析为一棵 抽象语法树 (AST) 。这棵树描述了模板的结构及其包含的指令、属性等信息。

    • 示例模板:

      vue
      复制代码
      <div id="app">
        <p>{{ message }}</p>
      </div>
      

      对应的 AST 树可能类似:

      json
      复制代码
      {
        "type": "Element",
        "tag": "div",
        "attrs": { "id": "app" },
        "children": [
          {
            "type": "Element",
            "tag": "p",
            "children": [
              { "type": "Expression", "content": "message" }
            ]
          }
        ]
      }
      
  2. 优化 (Optimization)

    • 静态节点会被标记为静态内容。这样在后续的渲染过程中,这些节点就可以跳过更新,提升性能。
    • 优化的主要目标是减少运行时的开销。
  3. 生成代码 (Code Generation)
    最后,编译器会将 AST 转换成 JavaScript 渲染函数(render 函数)字符串。
    示例:

    javascript
    复制代码
    function render() {
      return _c('div', { attrs: { id: 'app' } }, [
        _c('p', [_v(_s(message))])
      ]);
    }
    

2. 执行渲染函数 (Render Function Execution)

渲染函数在运行时会被执行,生成 虚拟 DOM (VNode)。

  • _c 是一个内部函数(createElement),用于创建虚拟节点。
  • _v 表示创建文本节点。
  • _s 用于将数据(如 message)转换为字符串。

生成的虚拟 DOM 树可能如下:

json
复制代码
{
  "tag": "div",
  "data": { "attrs": { "id": "app" } },
  "children": [
    {
      "tag": "p",
      "data": {},
      "children": [
        { "text": "Hello, Vue!" }
      ]
    }
  ]
}

3. 虚拟 DOM 转真实 DOM (VNode to Real DOM)

Vue 使用虚拟 DOM 来描述真实 DOM。当渲染函数返回虚拟 DOM 后,Vue 的虚拟 DOM diff 和 patch 过程会执行以下步骤:

  1. 初次渲染
    虚拟 DOM 树会被转换为真实 DOM,并插入到页面中。

  2. 数据变化触发更新

    • 当响应式数据发生变化时,Vue 会重新执行渲染函数,生成新的虚拟 DOM 树。
    • Vue 对新旧虚拟 DOM 树进行 diff 算法 比较,找出变化部分,并高效地更新真实 DOM。

4. 运行时与编译时的区别

  • 编译时 (Compiler-included build)
    如果使用的是 Vue 的完整版(如通过 <script> 引入的版本),模板会在浏览器中被动态编译为渲染函数。
  • 运行时 (Runtime-only build)
    如果使用的是运行时版本(如通过 Vue CLI 构建的版本),模板需要在构建阶段(比如用 webpack)提前被编译为渲染函数。

总结:Vue 的 templaterender 的过程是:

  1. 模板编译为渲染函数。

  2. 渲染函数执行生成虚拟 DOM。

  3. 虚拟 DOM 转换为真实 DOM,渲染到页面上。
    这种过程结合了编译时优化和运行时的高效更新,从而实现高性能的响应式 UI 渲染。

    较大概率引出下面的追问:

  • Vue 2 和 Vue 3 模板编译的区别?

    • Vue 3 引入 Block Tree 和动态节点标记,减少不必要的 diff。
  • AST 的作用是什么?

    • 用来描述模板的结构,为后续优化和代码生成提供基础。
  • 静态节点优化的原理是什么?

    • Vue 会标记静态节点,在数据更新时跳过它们的重新渲染,提升性能。
  • 虚拟 DOM 的作用是什么?

    • 提供性能优化的抽象层,通过 diff 算法高效更新真实 DOM。
  • 虚拟 DOM diff 的核心思路是什么?

    • 逐层对比新旧 VNode,尽量复用 DOM,最小化更新。