一、响应式原理:从 Object.defineProperty 到 Proxy
| 维度 | Vue2 | Vue3 |
|---|---|---|
| 实现方式 | Object.defineProperty 劫持 getter/setter | Proxy 直接代理对象(ES6 特性) |
| 监听颗粒度 | 只能监听属性,无法监听数组索引修改 | 可监听数组索引和对象属性,支持 Map/Set 等新类型 |
| 初始化性能 | 递归遍历对象属性,大型对象初始化慢 | 仅在属性被访问时建立响应式,初始化更快 |
| 内存占用 | 每个属性需绑定 getter/setter,内存开销大 | Proxy 代理更高效,内存占用减少 |
二、API 设计:从选项式到组合式
1. 组件写法对比
<!-- Vue2 选项式 API -->
<template>
<div>{{ count }}</div>
</template>
<script>
export default {
data() { return { count: 0 } },
methods: { increment() { this.count++ } },
mounted() { console.log('mounted') }
}
</script>
<!-- Vue3 组合式 API (setup) -->
<template>
<div>{{ count }}</div>
</template>
<script>
import { ref, onMounted } from 'vue';
export default {
setup() {
const count = ref(0);
const increment = () => count.value++;
onMounted(() => console.log('mounted'));
return { count, increment };
}
}
</script>
2. 组合式 API 优势
- 逻辑复用:通过自定义 Hook 函数(如
useMousePosition)复用逻辑,替代 Vue2 的 mixin(避免命名冲突)。 - 类型推导:TypeScript 支持更友好,自动推导变量类型。
- 代码组织:相关逻辑(如生命周期、计算属性)可集中在 setup 中,避免选项式的碎片化。
三、生命周期与钩子函数
| Vue2 钩子 | Vue3 对应钩子 | 组合式 API 钩子 |
|---|---|---|
beforeCreate | 移除(setup 替代初始化逻辑) | - |
created | 移除(setup 替代初始化逻辑) | - |
beforeMount | beforeMount | onBeforeMount |
mounted | mounted | onMounted |
beforeUpdate | beforeUpdate | onBeforeUpdate |
updated | updated | onUpdated |
beforeDestroy | beforeUnmount | onBeforeUnmount |
destroyed | unmounted | onUnmounted |
errorCaptured | errorCaptured | onErrorCaptured |
四、性能优化:编译与渲染引擎升级
-
编译优化
- Vue3 引入 模板编译时优化:
- 静态内容(如
<div>标题</div>)会被标记为static,不再进行响应式处理。 - 动态内容(如
{{ count }})会被编译为更高效的渲染函数。
- 静态内容(如
- Vue3 引入 模板编译时优化:
-
渲染性能
- Vue3 的 diff 算法升级:
- 新增
patchFlag标记节点类型,避免无变化节点的重复比对。 - 静态节点会被缓存,多次渲染时直接复用,减少 DOM 操作。
- 新增
- Vue3 的 diff 算法升级:
-
打包体积
- Vue3 支持 tree-shaking:仅打包实际使用的 API(如
ref、reactive),体积比 Vue2 减少约 40%。
- Vue3 支持 tree-shaking:仅打包实际使用的 API(如
五、新特性与语法糖
-
Composition API
- 允许在 setup 中组合使用响应式、生命周期等逻辑,替代 Vue2 的选项式组织方式。
-
Teleport(传送门)
- 允许组件模板渲染到 DOM 树的任意位置(如弹窗渲染到 body 下):
<teleport to="body"> <div class="modal">弹窗内容</div> </teleport>
- 允许组件模板渲染到 DOM 树的任意位置(如弹窗渲染到 body 下):
-
Suspense(异步组件加载)
- 处理异步组件加载状态,可定义加载中与错误状态:
<suspense> <template #default> <AsyncComponent /> </template> <template #fallback> <div>加载中...</div> </template> </suspense>
- 处理异步组件加载状态,可定义加载中与错误状态:
-
Emits 声明强化
- Vue3 中
emits可声明为数组或对象,支持参数类型校验:emits: { submit: (payload) => typeof payload === 'object' }
- Vue3 中
六、问题
1. 问:Vue3 为什么用 Proxy 替代 Object.defineProperty?
- 答:
Proxy支持监听数组索引和对象属性的新增/删除(如arr[0] = 1、delete obj.key)。Proxy是 ES6 原生 API,性能优于递归定义 getter/setter,且可直接代理 Map/Set 等新类型。- Vue2 中数组变异方法(如
push)需单独封装,而 Vue3 原生支持数组响应式。
2. 问:组合式 API 相比选项式有什么优势?
- 答:
- 逻辑复用:通过 Hook 函数复用代码,避免 mixin 的命名冲突。
- 类型推导:TypeScript 支持更完善,变量类型自动推导。
- 代码组织:相关逻辑(如数据、方法、生命周期)集中在 setup 中,避免选项式的碎片化。
3. 问:Vue3 如何优化大型应用的性能?
- 答:
- 编译时优化:静态内容标记为
static,减少响应式处理。 - diff 算法升级:
patchFlag标记节点类型,跳过无变化节点比对。 - tree-shaking:仅打包使用的 API,减少体积。
- 静态节点缓存:多次渲染时直接复用,减少 DOM 操作。
- 编译时优化:静态内容标记为