看完这篇文章,不再害怕Vue3的源码(二)

简介: 看完这篇文章,不再害怕Vue3的源码

看完这篇文章,不再害怕Vue3的源码(一)https://developer.aliyun.com/article/1426268


组件渲染

在 Vue 3 中,组件的渲染过程流程如下:

  1. 初始化渲染:当 Vue 3 创建一个组件实例时,Vue 3 会先对该组件进行初始化,并创建出其对应的 vnode。此时 Vue 3 将调用组件实例的 Setup 函数,来收集组件所需的响应式数据以及重新渲染组件所需的一些依赖关系。
  2. 模板编译:Vue 3 将会对组件的模板进行编译,将其转换为 VNode,并整理出 VNode 的父子关系。
  3. 虚拟 DOM 的生成:在此步骤中,Vue 3 将使用 VNode 即生成的虚拟 DOM 进行渲染,并将其插入到真实 DOM 中。
  4. 数据的更新:当组件内的数据发生变化时,Vue 3 将重复执行第二步至第四步的流程,生成新的 VNode,并将其与之前的 VNode 进行对比。
  5. DOM 的更新:在上一步中,当新旧虚拟节点进行比对后,Vue 3 将会根据比对结果执行相应的 DOM 操作
  6. 卸载流程:在组件卸载时,Vue 3 将从 DOM 中移除该组件,并进行一些相关的清理工作。

在 Vue 3 的渲染过程中,整个过程都是响应式的,也就是说,在响应式数据发生变化时,Vue 3 会自动重新渲染组件,这就是 Vue 3 状态响应式的核心机制。同时,Vue 3 的编译过程都是在运行时进行的,既可以使用 Vue 3 的模板语法,也可以直接使用 JavaScript 进行编写,使得 Vue 3 的渲染逻辑更加灵活。

VNode和diff算法

VNode 是 Vue 3 中的一个核心概念,它是一个关于视图层的抽象对象,包含了组件的层次结构和组件内部的状态信息。而 diff 算法是指在更新视图时,对比新旧 VNode 树,最小化地更改 DOM 树的算法,从而实现高效的视图更新。

在 Vue 3 中,当需要更新视图时,Vue 3 会通过对比新旧 VNode 树的差异,来确定需要哪些 DOM 操作,从而尽可能减少对 DOM 的操作,提高更新性能。

具体过程如下:

1. 对比 VNode:

Vue 3 会对新旧 VNode 树进行逐层对比,如果发现某个节点内容发生变化,或者子节点发生变化,就标记该节点需要更新。

2. 标记需要更新的节点:

对于标记为需要更新的节点,Vue 3 会将其放入队列中,标记为需要更新。

3. 执行更新:

Vue 3 会在下一次更新周期中,优先更新队列中的节点,从而完成对该节点的更新操作,这个过程中,Vue 3 使用了一些优化手段,以尽可能减少对 DOM 的操作,从而实现高效的视图更新。

需要注意的是,虽然 diff 算法可以有效地减少 DOM 的操作,但是在组件层级较深或者需要进行复杂计算时,仍然会影响页面性能,因此在开发时也需要谨慎优化。同时,对于静态节点尽量使用静态节点,可以通过开启 compileStatic 选项来把组件不需要改变的节点编译为静态节点,提升组件的性能。

异步组件和suspense

在 Vue 3 中,异步组件是指在组件渲染时,只有在需要时才会被加载的组件

异步组件的加载可以通过 import 函数来实现懒加载,从而提高应用的性能。使用异步组件时,需要将其定义为一个返回 Promise 的函数,该函数执行后返回组件对象

例如:

const AsyncComponent = () => import('./AsyncComponent.vue')
• 1

另外,在 Vue 3 中,还引入了 Suspense 组件来解决异步组件加载时,产生的卡顿或是白屏问题。Suspense 组件可以在异步组件加载完成前,指定一个占位符组件,并在异步组件加载完成后,显示真正的组件。这样,可以在页面加载过程中避免出现卡顿或是白屏的现象,提高用户体验。

使用 Suspense 组件时,需要在模板中添加一个 组件,在其中包含一个或多个异步组件,并指定一个 fallback 组件作为占位符。示例如下:

<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

需要注意的是,由于 Suspense 组件时 Vue 3 新引入的组件,因此在 Vue 2 中不支持。同时,使用异步组件和 Suspense 组件时也需要尽可能的避免触发过多的异步加载,避免影响页面性能。

V 编译器

模板解析和编译

在 Vue 3 中,模板解析和编译是 Vue 3 的核心功能之一,它们负责将模板转化为可执行的渲染函数,实现组件的渲染。

具体来说,模板解析和编译通过以下步骤来实现:

1. 解析模板:

Vue 3 会对模板进行解析,分析其中的 HTML 代码、指令以及用户自定义标签,并生成对应的 AST(抽象语法树)格式。

2. 生成渲染函数:

根据解析后的 AST,Vue 3 会对模板进行编译,生成可执行的渲染函数。在渲染函数中,Vue 3 会将模板中的数据绑定、计算属性和自定义指令等一系列特性编译为可执行的 JavaScript 代码,并通过生成闭包的方式实现了局部作用域,从而提高性能。

3. 生成 VNode:

在执行渲染函数时,Vue 3 会根据组件的状态信息,生成对应的 VNode(虚拟节点)树,这个 VNode 树中包含了组件的层次结构和组件内部数据以及指令等信息。

4. 插入到 DOM 树中:

最后,Vue 3 会将生成的 VNode 树和之前生成的旧的 VNode 树进行对比,并根据差异来决定 when 和 where 如何进行具体的 DOM 操作,最终将 VNode 树渲染到页面上。

需要注意的是,Vue 3 中的模板解析和编译都是在运行时进行的。这意味着 Vue 3 可以支持类似于 JSX 的模板语法,开发者可以将其视为模板那样编写,但实际上 Vue 3 会在运行时将其转化为可执行的 JavaScript 代码,从而实现高效的视图更新。同时,Vue 3 还引入了 compileStatic 选项,可以将组件的静态内容转换成静态节点,从而减少渲染时的重复计算和操作,从而提高组件的性能。

AST语法树

AST,全称是抽象语法树(Abstract Syntax Tree),是一种表示源代码抽象语法结构的树状结构。在 Vue 3 中,AST 被用于解析和编译模板,将模板转化为可执行的渲染函数。

在 Vue 3 中,模板首先会被解析成原始的 HTML 代码,包含了一些标签、属性和文本等内容。然后,Vue 3 会将这些原始的 HTML 代码,转换成 AST 树的形式,通过 AST 树可以表示出模板中各个元素的关系及作用,如父子关系,属性节点,文本节点等等。Vue 3 会在进行模板解析后,根据生成的 AST 树,利用编译器将其转换成可执行的 JavaScript 代码。这个过程中,Vue 3 会遍历 AST 树来寻找需要编译的部分,将其编译成原生 JavaScript 代码。

AST 有着广泛的应用,不仅仅是在 Vue 3 的模板解析和编译中使用。在前端开发中,很多工具和框架都会用到 AST 来实现相关功能,如 eslint、babel 等。AST 可以用于分析和优化代码的工具、代码的生成器和转换器等,可以大大提高代码的可维护性和开发效率。

需要注意的是,使用 AST 也需要注意它的性能,AST 节点过多或深度过大时,会导致解析速度变慢,影响应用性能。因此,开发者应该尽量避免出现过于复杂的 AST 树,从而提高应用的性能。

优化和静态提升

在 Vue 3 中,优化和静态提升是两种优化技术,用于提高组件的性能和减少重复渲染的次数。

1. 优化

优化是指在组件应用中,通过一些手段减少组件重新渲染的次数的技术。例如在使用 computed 属性的时候,只有当计算所依赖的数据发生变化时,才会进行重新计算和渲染视图,从而避免不必要的渲染。另外,Vue 3 还提供了 shouldUpdate 和 memo 方法,可以手动控制组件的重绘渲染,提高组件的性能。

2. 静态提升

静态提升是指在组件渲染时,把内部可能会执行多次的部分缓存起来,从而减少不必要的渲染次数。例如,在一个包含大量重复静态节点的组件中,可以使用 h() 函数把静态节点转换为 VNode 节点,从而避免不必要的重复渲染,提高组件的性能。

在 Vue 3 中,静态提升可以通过 compileStatic 选项来实现。compileStatic 选项可以将组件的静态内容转换成静态节点,并缓存起来,从而减少渲染时的重复计算和操作。开发者可以通过在模板中添加静态节点,使渲染时的计算量变小,从而提高应用的性能。

需要注意的是,在使用静态提升时,要避免将动态节点变为静态节点,否则会导致组件渲染不正常。同时,要尽可能地减少代码中的重复节点,从而提高静态提升的效果。

VI 其他重要概念和实现

插槽

Vue 3 中,插槽是一种将父组件中的内容传递到子组件中进行渲染的技术

插槽功能可以让开发者在父组件中定义一些内容,然后将这些内容传递到子组件中进行渲染,从而实现更加灵活的组件设计

在 Vue 3 中,可以使用 v-slot 指令来定义和使用插槽。

以下是使用插槽的基本步骤:

1. 在父组件中,使用 标签定义插槽。可以通过 name 属性来给插槽命名。

<template>
  <div>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

2. 在子组件中,使用 v-slot 指令来引用父组件中定义的插槽。可以使用 v-slot 的简写语法 # ,并通过 slot 属性来引用对应的插槽。

<template>
  <div>
    <header>
      <slot name="header"></slot>
    </header>
    <main>
      <slot></slot>
    </main>
    <footer>
      <slot name="footer"></slot>
    </footer>
  </div>
</template>
<template>
  <BaseLayout>
    <template #header>
      <h1>Welcome</h1>
    </template>
    <template>
      <p>Hello, Vue 3!</p>
    </template>
    <template #footer>
      <p>Have a nice day!</p>
    </template>
  </BaseLayout>
</template>

需要注意的是,在 Vue 3 中,通过 v-slot 可以使用插槽的具名和默认语法,而在 Vue 2 中仅支持具名插槽。

Vue 3 的插槽功能可以大大提高组件的灵活性,使得父组件可以更加自由地向子组件中传递数据和内容。


看完这篇文章,不再害怕Vue3的源码(三)https://developer.aliyun.com/article/1426271

相关文章
|
29天前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
467 139
|
24天前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
181 1
|
6月前
|
缓存 JavaScript PHP
斩获开发者口碑!SnowAdmin:基于 Vue3 的高颜值后台管理系统,3 步极速上手!
SnowAdmin 是一款基于 Vue3/TypeScript/Arco Design 的开源后台管理框架,以“清新优雅、开箱即用”为核心设计理念。提供角色权限精细化管理、多主题与暗黑模式切换、动态路由与页面缓存等功能,支持代码规范自动化校验及丰富组件库。通过模块化设计与前沿技术栈(Vite5/Pinia),显著提升开发效率,适合团队协作与长期维护。项目地址:[GitHub](https://github.com/WANG-Fan0912/SnowAdmin)。
890 5
|
2月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
335 11
|
1月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
222 0
|
3月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
400 1
|
3月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
223 0
|
4月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
130 0
|
6月前
|
JavaScript API 容器
Vue 3 中的 nextTick 使用详解与实战案例
Vue 3 中的 nextTick 使用详解与实战案例 在 Vue 3 的日常开发中,我们经常需要在数据变化后等待 DOM 更新完成再执行某些操作。此时,nextTick 就成了一个不可或缺的工具。本文将介绍 nextTick 的基本用法,并通过三个实战案例,展示它在表单验证、弹窗动画、自动聚焦等场景中的实际应用。
552 17
|
6月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
1680 0