前言
Vue2 和 Vue3 的区别是面试中绕不开的高频考点。本文聚焦最常被问到的核心差异,帮你快速抓住重点。
一、响应式原理(必问)
这是两种方案最本质的差异,也是面试必考题。
Vue2 — Object.defineProperty
1 | Object.defineProperty(obj, key, { |
三大缺陷:
- 无法检测对象属性新增/删除 → 需要
Vue.set()/Vue.delete() - 无法监听数组索引和 length → 重写 7 个数组方法(push/pop/shift/unshift/splice/sort/reverse)
- 初始化递归遍历所有属性,大数据量时性能差
Vue3 — Proxy
1 | new Proxy(target, { |
解决了 Vue2 的全部痛点:
- ✅ 检测属性增删、数组索引和
length变化 - ✅ 懒代理 — 按需递归,初始化更快
- ✅ 支持 Map、Set、WeakMap、WeakSet
面试一句话总结:
defineProperty劫持的是属性,Proxy劫持的是整个对象。
二、Composition API vs Options API
这也是面试最常问的问题之一。
1 | // Vue2 Options API — 按选项拆分,同类逻辑分散 |
| 对比点 | Options API | Composition API |
|---|---|---|
| 代码组织 | 按选项分类,逻辑分散 | 按功能聚合,高内聚 |
| 逻辑复用 | Mixins(命名冲突、来源不清晰) | Composables(纯函数,来源可追踪) |
| this | 依赖 this,不利于类型推导 |
无 this,天然支持 TS |
| Tree-Shaking | 不支持 | 按需引入,打包更小 |
<script setup>语法糖是推荐的写法,代码更简洁。
三、生命周期变化
Vue3 映射原名,允许在一个组件中挂载多个钩子。
| Vue2 | Vue3(Options) | Vue3(Composition) |
|---|---|---|
beforeCreate |
beforeCreate |
setup() 本身 |
created |
created |
setup() 本身 |
beforeMount |
beforeMount |
onBeforeMount |
mounted |
mounted |
onMounted |
beforeUpdate |
beforeUpdate |
onBeforeUpdate |
updated |
updated |
onUpdated |
beforeDestroy |
beforeUnmount |
onBeforeUnmount |
destroyed |
unmounted |
onUnmounted |
新增
onRenderTracked、onRenderTriggered两个调试钩子。
四、v-if / v-for 优先级
这是高频陷阱题。
| 版本 | 同级优先级 | 后果 |
|---|---|---|
| Vue2 | v-for > v-if |
先循环再判断,浪费性能 |
| Vue3 | v-if > v-for |
v-if 中访问不到 v-for 的变量,直接报错 |
无论哪个版本,永远不要同时使用
v-if和v-for,用<template>包裹或用computed过滤。
五、v-model 变化
| 功能 | Vue2 | Vue3 |
|---|---|---|
| 单个绑定 | v-model="val" |
v-model="val" |
| 多个绑定 | 不支持,用 .sync |
v-model:title v-model:content |
| .sync 修饰符 | :title.sync |
移除,合并为 v-model:title |
| 默认 prop/event | value / input |
modelValue / update:modelValue |
| 自定义修饰符 | 不支持 | modelModifiers 可自定义 |
1 | <!-- Vue3 多 v-model --> |
六、已删除的 API
| 已删除 | 替代方案 |
|---|---|
filters 过滤器 |
computed / 全局方法 |
$on $off $once |
mitt / provide + inject |
$children |
$refs |
$listeners |
合并到 $attrs |
Vue.set Vue.delete |
Proxy 直接操作 |
Vue.extend |
defineComponent |
new Vue() |
createApp() |
七、性能优化
| 机制 | 原理 | 效果 |
|---|---|---|
| 静态提升 | 静态节点提升到 render 外,不参与 Diff | 减少 VNode 创建 |
| 静态标记 | 编译阶段标记动态节点(PatchFlag) | Diff 时跳过静态节点 |
| Block Tree | 只记录动态子节点,组成扁平数组 | Diff 不递归整棵树 |
| 事件缓存 | 编译时缓存事件函数引用 | 避免子组件无意义更新 |
1 | // 静态提升示意:编译前 |
八、其他关键差异
| 差异点 | Vue2 | Vue3 |
|---|---|---|
| 根节点 | 必须单个根节点 | Fragment 支持多根 |
| TypeScript | 类型支持差 | 源码用 TS 重写 |
| 打包体积 | ~32KB | ~16KB(Tree-Shaking) |
| Teleport | 无 | 内置 <Teleport> |
| Suspense | 无 | 内置 <Suspense> |
| 入口 | new Vue({ render: h => h(App) }).$mount() |
createApp(App).mount() |
总结
面试高频顺序建议这样记:
- 响应式 —
defineProperty→Proxy,解决属性增删和数组监听 - API 风格 — Options API → Composition API,逻辑复用更优雅
- 生命周期 —
destroyed→unmounted,setup替代beforeCreate+created - v-if / v-for — 优先级反转,永远别同时用
- v-model — 支持多个绑定,
.sync被合并 - 删除的 API — filters、
$on/$off、$children - 性能 — 静态提升 + 静态标记 + Block Tree
- 新特性 — Fragment、Teleport、Suspense、Tree-Shaking
新项目直接上 Vue3,老项目用 @vue/compat 渐进式迁移。
内容由 AI 生成,仅供参考。本文发布于 码上学习,转载请注明出处。