vue2和vue3的区别

性能优化

Vue 3 在性能方面有显著提升。它引入了一个全新的虚拟 DOM 算法(Faster Virtual DOM),该算法使用了更有效的数据结构和算法,使得在渲染大型组件树时更快速。
另外,Vue 3 还引入了静态树提升(Static Tree Hoisting)技术,通过在编译阶段将静态部分的节点提升为常量,进一步减少了运行时的开销。

虚拟 DOM 算法

1. 片段(Fragment)和合并(Patch):

Vue 3 引入了 Fragment 的概念,它将组件的模板划分为多个小片段。这样一来,在更新时可以只更新发生变化的部分,而不需要重新渲染整个组件。这种局部更新的机制可以大大提高渲染性能。
Patch 是 Vue 3 中的一个关键概念,用于将虚拟 DOM 节点的变化应用到实际的 DOM 上。Vue 3 通过对比新旧虚拟 DOM 树的差异,并将这些差异应用到实际的 DOM 上,来完成更新操作。

2. 静态树提升(Static Tree Hoisting):

静态树提升是 Vue 3 的一个优化技术,它允许编译器在编译时识别出组件模板中的静态部分,并将其提升为常量。这样一来,每次渲染时都不需要重新计算静态部分,从而减少了渲染的开销。
静态树提升使得 Vue 3 在处理静态内容时能够更快地完成渲染,尤其是对于大型组件树的渲染效率提升尤为显著。

3. 事件侦听器的优化:

在 Vue 3 中,事件侦听器的绑定和解绑过程得到了优化,使得事件处理的性能得到提升。Vue 3 使用更有效的数据结构来管理事件侦听器,减少了事件绑定和解绑的开销。
这种优化使得在频繁触发事件的情况下,Vue 3 的性能表现更好,同时也降低了内存的占用。

4. 批量更新:

Vue 3 引入了批量更新机制,通过将多个更新操作合并成一个更新批次来减少渲染的次数。这样可以避免不必要的重复渲染,提高了渲染效率。
批量更新机制还可以降低触发重排和重绘的次数,从而减少了浏览器的性能开销,提升了整体的渲染性能。

Composition API

Vue 3 引入了 Composition API,这是一个基于函数的 API,允许开发者根据逻辑功能组织代码,而不是像 Vue 2 中的 Options API 那样基于选项的组件定义。Composition API 更加灵活,使得代码复用和组件逻辑的组织更加清晰。

Composition API 和 Options API

1. Options API

Options API 是 Vue 2.x 中默认使用的 API。它通过将组件的选项(options)放置在一个对象中来组织组件的逻辑。这些选项可以包括 datamethodscomputedwatch 等。

Options API 适合于较小规模的组件或者简单的应用程序。通过将相关的逻辑放置在对应的选项中,使得组件的结构相对清晰,易于理解和维护。

Options API 的缺点在于,当组件变得较大或者复杂时,所有的选项都放在一个对象中会导致代码结构变得混乱,不易于复用和组织。

2. Composition API

Composition API 是 Vue 3.x 中引入的一种新的 API。它通过使用函数来组织和管理组件的逻辑,使得代码更加灵活和可组合。
Composition API 允许开发者将组件的逻辑代码按照功能划分为多个函数,然后通过在组件中使用这些函数来组装组件的逻辑。这样一来,可以更自然地组织和复用代码,使得组件的结构更清晰。
Composition API 提供了更多的灵活性,使得开发者可以更轻松地处理复杂的逻辑需求。它也更适合于跨组件共享逻辑或者在不同组件之间进行代码复用。

Tree-shaking 支持

Vue 3 对 Tree-shaking 有更好的支持。通过对模块的静态分析,Vue 3 可以更有效地移除未使用的代码,从而减小最终构建产物的大小。

TypeScript 支持

Vue 3 对 TypeScript 的支持更加完善。它提供了更全面和精确的类型定义,使得在使用 TypeScript 开发 Vue 应用时更加顺畅。

原先 vue2 中 对 javascript 使用 flow 进行类型检测

响应性系统重构

Vue 3 对其响应性系统进行了重构,使其更为强大和高效。Vue 3 采用了 Proxy 来实现响应式,相比 Vue 2 中的 Object.defineProperty,Proxy 具有更好的性能和更灵活的用法。

1. Object.defineProperty

Object.definePropertyES5 中引入的一种对象属性定义方法,用于直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
它通过定义属性的 getset 方法来实现对属性的拦截和代理。通过这种方式,可以在属性被读取或者赋值时执行一些自定义的逻辑。
Object.defineProperty 是针对单个属性进行操作的,需要针对每个需要代理的属性分别定义,相对来说比较繁琐。

2. Proxy

ProxyES6 中引入的一种全新的代理机制,它提供了一种通用的方法来拦截对象的操作,并且可以对整个对象进行代理,而不是针对单个属性。
通过 Proxy,可以拦截对象的诸多操作,包括属性的读取、赋值、删除等。它提供了一系列的拦截方法,比如 getsetdeleteProperty 等。
Proxy 是一种更加灵活和强大的代理机制,相比于 Object.defineProperty,它可以更方便地实现对整个对象的代理,并且可以对所有属性进行统一的处理。

Object.defineProperty 主要用于对单个属性进行拦截和代理,而 Proxy 则是一种更为通用和强大的代理机制,可以对整个对象进行代理,并且提供了更多的拦截方法。在现代的 JavaScript 开发中,通常推荐使用 Proxy 来实现对象的拦截和代理,因为它提供了更多的功能和更灵活的使用方式。

Teleport

Vue 3 引入了 Teleport 特性,这是一种可以将子组件的内容渲染到父组件的指定DOM 位置的机制。Teleport 可以用于实现模态框、弹出菜单等组件,使得它们的位置更加灵活。

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
<template>
<div>
<button @click="toggleModal">Toggle Modal</button>
<teleport to="body">
<modal v-if="showModal" />
</teleport>
</div>
</template>

<script>
import { ref } from "vue";
import Modal from "./Modal.vue";

export default {
components: {
Modal,
},
setup() {
const showModal = ref(false);

const toggleModal = () => {
showModal.value = !showModal.value;
};

return {
showModal,
toggleModal,
};
},
};
</script>

在上面的例子中,我们通过 Teleport 将 Modal 组件的内容传送到了 body 元素下,从而实现了模态框的渲染。

Suspense

Vue 3 引入了 Suspense 特性,这是一种用于处理异步组件渲染的机制。开发者可以使用 Suspense 来优雅地处理组件加载过程中的加载状态,以及在组件加载失败时的错误处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<suspense>
<template #default>
<async-component />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</template>

<script>
import { defineAsyncComponent } from "vue";

const AsyncComponent = defineAsyncComponent(() =>
import("./AsyncComponent.vue")
);

export default {
components: {
AsyncComponent,
},
};
</script>

在上面的例子中,Suspense 包裹了一个异步组件AsyncComponent,并通过fallback插槽提供了一个加载状态的占位符。当异步组件加载时,会先显示 fallback 中的内容,直到异步组件加载完成后,才会显示 AsyncComponent 的内容