《Vue.js设计与实现》精读|编译器和渲染器是 Vue 的核心组成部分

框架设计讲究全局视角的把控,一个项目就算再大,也是存在一条核心思路的,并围绕核心展开。

如何设计一个声明式的 UI 框架

了解编写前端页面都涉及哪些内容

  • DOM 元素:例如是 div 标签还是 a 标签。
  • 属性:如 a 标签的 href 属性,再如 id、class 等通用属性。
  • 事件:如 click、keydown 等。
  • 元素的层级结构:DOM 树的层级结构,既有子节点,又有父节点。

Vue3 如何声明式地描述上述内容

  • 使用与 HTML 标签一致的方式来描述 DOM 元素,例如描述一个 div 标签时可以使用
  • 使用与 HTML 标签一致的方式来描述属性,例如
  • 使用与 HTML 标签一致的方式来描述层级结构,例如一个具有 span 子节点的 div 标签
  • 使用 :v-bind 来描述动态绑定的属性,例如
  • 使用 @v-on 来描述事件,例如点击事件 <div @click="handler">;

渲染器 - 渲染虚拟DOM到浏览器页面

Vue 将 UI 声明式的描述出来后会转换成虚拟DOM,虚拟DOM的原理这里暂时不讲,下次会专门讲的。

📌 渲染器的作用:就是把虚拟 DOM 渲染为真实 DOM。精髓在于后续的更新,它会通过 Diff 算法找出变更点,并且只会更新需要更新的内容。

渲染器实现思路:

  1. 创建元素:把 vnode.tag 作为标签名称来创建 DOM 元素
  2. 为元素添加属性和事件:遍历 vnode.props 对象,如果 key 以 on 字符开头,说明它是一个事件,把字符 on 截取掉后再调用 toLowerCase 函数将事件名称小写化,最终得到合法的事件名称,例如 onClick 会变成 click,最后调用 addEventListener 绑定事件处理函数
  3. 处理 children:如果 children 是一个数组,就递归地调用 renderer 继续渲染,注意,此时我们要把刚刚创建的元素作为挂载点(父节点);如果 children 是字符串,则使用 createTextNode 函数创建一个文本节点,并将其添加到新创建的元素内

编译器 - 将模板编译为渲染函数

📌 编译器的作用:编译模板 → 生成渲染函数

如下是一个模板代码片段

html 复制代码
<div @click="handler">
   点击我!
</div>

经过编译器后,会变成如下渲染函数

javascript 复制代码
render() {
    return h('div', { onClick: handler }, '点击我!')
}

编译器和渲染器如何配合工作

📌 编译器、渲染器都是 Vue.js 的核心组成部分,它们共同构成一个有机的整体,不同模块之间互相配合,进一步提升框架性能.

编译器和渲染器之间是存在信息交流的,它们互相配合使得性能进一步提升,而它们之间交流的媒介就是虚拟 DOM 对象。

举例说明

假设有如下模板

html 复制代码
<div id="foo" :class="cls"></div>

编译器会把这段代码编译成渲染函数

javascript 复制代码
render() {
  // 为了效果更加直观,这里没有使用 h 函数,而是直接采用了虚拟 DOM 对象
  // 下面的代码等价于:
  // return h('div', { id: 'foo', class: cls })
  return {
    tag: 'div',
    props: {
      id: 'foo',
      class: cls
    }
  }
}

在这段代码中,cls 是一个变量,它可能会发生变化。我们知道渲染器的作用之一就是寻找并且只更新变化的内容,所以当变量 cls 的值发生变化时,渲染器会自行寻找变更点。对于渲染器来说,这个"寻找"的过程需要花费一些力气。

编译器能识别出哪些是静态属性,哪些是动态属性,在生成代码的时候完全可以附带这些信息

javascript 复制代码
render() {
  return {
    tag: 'div',
    props: {
      id: 'foo',
      class: cls
    },
    patchFlags: 1 // 假设数字 1 代表 class 是动态的
  }
}

如上面的代码所示,在生成的虚拟 DOM 对象中多出了一个 patchFlags 属性,我们假设数字 1 代表" class 是动态的",这样渲染器看到这个标志时就知道:"哦,原来只有 class 属性会发生改变。"对于渲染器来说,就相当于省去了寻找变更点的工作量,性能自然就提升了。

面试真题

讲讲 Vue 中渲染器和编译器的作用

渲染器的作用:

  • 负责将虚拟 DOM 渲染成实际的浏览器 DOM,使页面可见。

编译器的作用:

  • 负责将组件模板编译成渲染函数,从而实现虚拟 DOM 的生成。

渲染器和编译器的关系:

  • 它们协同工作以实现 Vue 的核心功能。编译器可以进行代码优化,例如静态节点提取、事件处理器的代码内联等。这些优化可以减少渲染函数的复杂性和运行时开销
相关推荐
SchuylerEX2 分钟前
第六章 JavaScript 互操(2).NET调用JS
前端·c#·.net·blazor·ui框架
东风西巷1 小时前
Rubick:基于Electron的开源桌面效率工具箱
前端·javascript·electron·软件需求
探码科技1 小时前
AI知识管理软件推荐:九大解决方案与企业应用
前端·ruby
编程小黑马1 小时前
解决flutter 在控制器如controller 无法直接访问私有类方法的问题
前端
unfetteredman2 小时前
Error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found
前端·javascript·vite
云存储小精灵2 小时前
Dify x 腾讯云 COS MCP:自然语言解锁智能数据处理,零代码构建 AI 新世界
前端·开源
山间板栗2 小时前
微信小程序环境变量设置方案
前端
电商API大数据接口开发Cris2 小时前
Java Spring Boot 集成淘宝 SDK:实现稳定可靠的商品信息查询服务
前端·数据挖掘·api
pepedd8642 小时前
LangChain:大模型开发框架的全方位解析与实践
前端·llm·trae
HANK2 小时前
KLineChart 绘制教程
前端·vue.js