1 组件优化
1 Fragment(多根组件)
- Vue2 限制:组件模板必须单根节点,导致冗余包裹元素。
- Vue3 改进:支持多根节点,减少 DOM 层级。
2 Teleport(传送门)
- 功能:将组件渲染到 DOM或者是vue实例 任意位置(如全局弹窗)。
- 场景:解决样式隔离或 DOM 嵌套限制问题。
需要注意的是,虽然 DOM 插头被传送到另一个地方,但它的父组件仍然是当前组件,这一点必须牢记,否则会导致样式、交互等问题。
Teleport 组件不仅支持具体的 id/选择器,还可以为to
属性绑定一个 Vue 组件实例,比如:
xml
<template>
<teleport :to="dialogRef">
<div>这里是瞬移到Dialog组件里的组件</div>
</teleport>
<Dialog ref="dialogRef"></Dialog>
</template>
总之,Teleport
组件是 Vue3 中新增的一个非常有用的组件,可以方便地实现一些弹出框、提示框等组件的功能,提高了开发效率。
3 Suspense(异步组件)
- 功能:优雅处理异步组件加载状态,defalut插槽存放加载后内容,fallback插槽存放加载中的过渡内容。
- 场景:数据请求、动态导入组件时的加载中/错误状态。
2 TS支持
3 保留原来的Options API,新增Composition API
提升了逻辑复用;代码组织;函数式写法更适合ts。
其中vue3新增了reactive函数和ref函数
- reactive函数定义复杂数据类型的响应式数据,在js和模板中可直接使用
- ref函数定义所有数据类型的响应式数据,在js中要.value来调用,模板中直接使用
遵循:尽量使用 ref
函数支持所有场景,确定字段的对象使用 reactive
可以省去.value
。
- toRef:用于将某个对象的某个属性转换为响应式引用
- toRefs:用于将某个响应式对象的所有属性转换为响应式引用
js
import { reactive, toRef } from 'vue';
const state = reactive({ count: 0 });
const countRef = toRef(state, 'count');
console.log(countRef.value); // 0
js
import { reactive, toRefs } from 'vue';
const state = reactive({ count: 0, name: 'Vue' });
const { count, name } = toRefs(state);
console.log(count.value); // 0
console.log(name.value); // Vue
拓展点:
- watch:可监听单个或多个源,有明确监听目标的优先使用watch进行精确监听,写法:watch(source, callback, options?)
- watchEffect:立即执行fn函数,自动追踪所有访问的响应式属性,无旧值处理逻辑
watch:
js
// 监听单个ref
const count = ref(0)
watch(count, (newVal, oldVal) => {
console.log(`Count changed from ${oldVal} to ${newVal}`)
})
// 监听getter函数
watch(
() => state.user.age,
(age) => console.log('Age updated:', age)
)
// 监听多个源
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
// 处理变化逻辑
})

watchEffect:
js
const stop = watchEffect((onCleanup) => {
console.log('Count:', count.value)
onCleanup(() => {
console.log('Cleanup previous effect')
})
})
// 停止监听
stop()
4 生命周期变化
阶段 | 组合式 API 钩子 | 选项式 API 钩子 | 调用时机说明 |
---|---|---|---|
创建阶段 | setup() |
beforeCreate /created |
组合式 API 中 setup() 替代了 Vue 2 的这两个钩子,统一处理初始化逻辑 |
挂载阶段 | onBeforeMount |
beforeMount |
模板编译完成但未挂载到 DOM |
onMounted |
mounted |
DOM 挂载完成,可安全操作 DOM 元素 | |
更新阶段 | onBeforeUpdate |
beforeUpdate |
数据变化后,虚拟 DOM 重新渲染前触发 |
onUpdated |
updated |
虚拟 DOM 重新渲染并应用补丁后触发 | |
销毁阶段 | onBeforeUnmount |
beforeUnmount |
实例销毁前(Vue 2 的 beforeDestroy 更名,语义更清晰) |
onUnmounted |
unmounted |
实例销毁后(Vue 2 的 destroyed 更名) |
关键说明:
- 命名变化:Vue 3 钩子名称更语义化(如
unmount
替代destroy
),组合式 API 需添加on
前缀。 -
setup()
整合:替代 Vue 2 的beforeCreate
和created
,集中处理响应式数据、方法等初始化逻辑。 - 选项式 API 兼容:Vue 3 仍支持选项式写法(如
mounted
),但推荐使用组合式 API。
setup函数是组合式API的入口函数,默认导出配置选项,setup函数声明,返回模板需要数据与函数。
setup
函数是Vue3
特有的选项,作为组合式API的起点- 从组件生命周期看,它在
beforeCreate
之前执行 - 函数中
this
不是组件实例,是undefined
- 如果数据或者函数在模板中使用,需要在
setup
返回 - 今后在vue3的项目中几乎用不到
this
, 所有的东西通过函数获取。
5 底层响应式原理不同
Vue2使用的是Object.defineProperty()来劫持各个属性的setter/getter,在数据发生变化的时候通知订阅者更新视图。
缺点:
- 无法检测到对象的属性添加和删除
- 无法检测到数组的内部变化,因此Vue2通过重写数组方法来实现数组的响应式
- 需要遍历整个对象,如果对象嵌套过深,需要递归遍历,性能会下降
Vue3使用的是Proxy来劫持整个对象,从而实现响应式。Proxy可以直接监听对象和数组的变化,不需要遍历整个对象,性能会更好。
- 引用数据类型:Proxy
- 基本数据类型:使用对象的属性来监听------> RefImpl(RefImpl 是 Vue3 中通过 ref() 创建的响应式引用对象内部实现类)
优点:
- 可以监听到对象和数组的变化
- 可以监听到对象属性的添加和删除
- 浅层监听,只有当对象的深层属性被使用到时才会递归遍历监听。减少了性能开销。
vue3的proxy优势
- proxy性能整体上优于Object.defineProperty
- vue3支持更多数据类型的劫持(vue2只支持Object、Array;vue3支持Object、Array、Map、WeakMap、Set、WeakSet)
- vue3支持更多时机来进行依赖收集和触发通知(vue2只在get时进行依赖收集,vue3在get/has/iterate时进行依赖收集;vue2只在set时触发通知,vue3在set/add/delete/clear时触发通知),所以vue2中的响应式缺陷vue3可以实现
- vue3做到了"精准数据"的数据劫持(vue2会把整个data进行递归数据劫持,而vue3只有在用到某个对象时,才进行数据劫持,所以响应式更快并且占内存更小)
- vue3的依赖收集器更容易维护(vue3监听和操作的是原生数组;vue2是通过重写的方法实现对数组的监控)
Vue3 的 Diff 优化策略
1.靶向更新(Targeted Updates)
-
补丁标志(Patch Flags) 在编译阶段分析模板,为动态绑定的节点添加标记(如 TEXT、CLASS、PROPS),标记其动态部分类型。 效果:Diff 时只需检查标记的动态属性,跳过静态内容。
-
静态提升(Static Hoisting)
将静态节点(无动态绑定)提取到渲染函数外部,避免重复创建 VNode。
效果:减少内存占用和 Diff 时的比对次数。
- 块树(Block Tree)与动态锚点
块(Block) 将模板中的动态节点(含 v-if、v-for 或动态插槽)包裹为「块」,每个块追踪其内部动态子节点。
动态锚点 在块内记录动态节点的位置,更新时直接定位到动态部分,跳过静态结构。
效果:Diff 范围从整棵树缩小到块内动态节点,复杂度从 O(n) 降低到 O(动态节点数)。
- 最长递增子序列(LIS)优化列表更新
问题场景:当列表元素顺序变化时,Vue2 的双端比较可能导致多次 DOM 移动。
Vue3 解决方案: 在确定新旧子节点映射后,使用 最长递增子序列算法 找到最少的 DOM 移动路径。
示例: 新旧子节点索引序列为 [2, 3, 1, 4] → LIS 为 [2, 3, 4],只需移动节点 1 到正确位置。
效果:最小化 DOM 移动次数,提升列表渲染性能。
6 vue3 hooks
Hooks是一种特殊的函数,它可以让你在函数组件中使用状态和其他Vue特性。Vue3中的Hooks通常具有以下特征:
- 以"use"作为函数名称前缀
- 返回一个包含响应式数据或方法的对象
- 可以使用其他Hooks
- 遵循组合式函数的设计模式
与 Vue2 Mixins 的对比
对比项 | Vue3 Hooks | Vue2 Mixins |
---|---|---|
逻辑隔离 | 闭包封装,状态独立 | 共享上下文,易命名冲突 |
代码组织 | 函数式,逻辑集中 | 分散在多个选项(data、methods) |
调试友好性 | 状态来源清晰,易追踪 | 数据来源隐式,调试困难 |
使用案例: blog.csdn.net/BillKu/arti...
7 createApp 是 Vue3 应用创建的入口函数,用于生成 Vue 应用实例,是 Vue3 官方推荐的应用初始化方式
Vue3 的实现了多实例隔离机制,在Vue2(new Vue())中只能有一个全局唯一的应用实例,只能挂载到一个根元素,并且全局共享配置。但是在vue3(createApp())中允许多实例共存 ,每个实例独立配置(组件/插件/指令)并且每个实例可挂载到不同容器 。
pinia
vuex与pinia区别:
- API设计与使用方式:
- Vuex: 需要定义state、mutations、actions和getters四个核心概念: 同步状态修改必须通过mutations提交。 异步操作需在actions中通过commit触发mutations
- Pinia: 简化API流程,直接通过actions同步/异步修改state,无需mutations,代码量减少40%。
- TypeScript支持:
- Vuex: 类型系统复杂,需手动定义类型装饰器,在大型项目中维护成本较高。
- Pinia: 原生支持类型推断,可直接通过this访问状态并自动推导类型,类型安全性和开发效率更高。
- 模块化管理:
- Vuex: 采用命名空间模块化设计,嵌套结构易导致代码复杂度增加,模块间依赖管理困难。
- Pinia: 每个store独立存在,支持扁平化组合式模块管理,通过defineStore实现天然代码分割。
注意:storeToRefs 是 Pinia 提供的一个工具函数,用于在 Vue 3 的组合式API中解构Store的状态(state)或计算属性(getters)时保持响应性。
js
import { storeToRefs } from 'pinia'
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
const { name, age, isAdult } = storeToRefs(userStore)