🟢 Vue 面试速答

响应式原理 / 生命周期 / 组件通信 / v-if vs v-show / computed vs watch / Diff 算法
通俗易懂 · 面试导向 · 一句话能答上来

① 响应式原理(最高频)

QVue 的响应式原理是什么?Vue 2 和 Vue 3 有什么区别?
一句话:数据变了,页面自动更新。Vue 帮你监听数据,变了就重新渲染。

Vue 2:用 Object.defineProperty 劫持每个属性的 getter/setter。缺点:① 新增属性不响应(要用 $set);② 数组下标修改不响应;③ 深层对象要递归遍历,性能差。

Vue 3:用 Proxy 代理整个对象。优点:① 新增属性自动响应;② 数组直接改也响应;③ 懒代理(访问到才代理子属性),性能好。

类比:Vue 2 像给每个房间装监控(逐个劫持),新盖的房间没监控;Vue 3 像给整栋楼大门装门禁(Proxy 代理整体),进出都能感知。
Qref 和 reactive 的区别?什么时候用哪个?
refreactive
适合基本类型(string/number/boolean)对象/数组
访问需要 .value(模板里自动解包)直接访问属性
原理RefImpl 包装,value 改了触发更新Proxy 代理对象
解构解构不丢响应性解构会丢响应性(要用 toRefs)
建议:基本类型用 ref,对象用 reactive。不确定就用 ref(都能用)。

② 生命周期

QVue 3 的生命周期有哪些?和 Vue 2 有什么区别?
Vue 3(Composition API)
onBeforeMount → onMounted → onBeforeUpdate → onUpdated → onBeforeUnmount → onUnmounted

对应 Vue 2:beforeCreate/created 没了(setup 替代),beforeMount→onBeforeMount,mounted→onMounted,beforeUpdate→onBeforeUpdate,updated→onUpdated,beforeDestroy→onBeforeUnmount,destroyed→onUnmounted。

最常用onMounted(发请求、操作DOM)、onUnmounted(清定时器、解绑事件)。
Q在哪个生命周期发请求?为什么?
onMounted。原因:① DOM 已经渲染完,可以操作 DOM;② SSR 时 onMounted 不会执行(服务端没有 DOM),避免报错。

如果需要在 setup 阶段就获取数据(不等 DOM),可以直接在 setup 里调 async 函数,但要自己处理 loading 状态。推荐还是用 onMounted。

③ 组件通信(必考)

场景方案说明
父→子props父组件传数据,子组件 defineProps 接收
子→父emit子组件 defineEmits 触发,父组件监听
父子双向v-modelVue 3 用 modelValue + update:modelValue
祖→孙跨级provide / inject祖先 provide,任意后代 inject
兄弟/任意组件Pinia / 事件总线推荐 Pinia;小型项目可用 mitt 库做事件总线
父→子方法调用defineExpose + ref子组件暴露方法,父组件用 ref 调用

④ v-if vs v-show 等高频对比

Qv-if 和 v-show 的区别?
v-if:真正条件渲染——false 时元素不存在于 DOM。切换开销大(反复创建/销毁)。
v-show:始终渲染,只是切换 display:none。初始渲染开销大,切换开销小。

选型:频繁切换用 v-show;条件很少改变用 v-if。v-if 有更高的优先级(v-if=false 时 v-show 也不会渲染)。
Qcomputed 和 watch 的区别?
computed:计算属性,基于依赖缓存,依赖不变不重算。必须有返回值。适合"派生数据"。
watch:监听器,数据变了就执行回调(可以有副作用)。适合"数据变了要做点什么"(发请求、操作 DOM)。

一句话:computed 管"算出新值",watch 管"变了干什么事"。
Qv-for 为什么要加 key?用 index 有什么问题?
key 的作用:帮 Diff 算法识别节点,高效复用 DOM。没有 key,Vue 默认"就地复用",可能渲染错误。

用 index 的问题:列表中间插入/删除时,index 会错位,导致状态错乱(比如输入框内容串了)。
正确做法:用数据的唯一 id 作为 key。
QnextTick 是干什么的?
等 DOM 更新完再执行。Vue 更新 DOM 是异步的(批处理),你改了数据立刻操作 DOM 拿到的是旧的。

场景:改了数据让元素显示,然后想 focus 这个元素 / 获取它的高度——要放到 nextTick 里。

⑤ 虚拟 DOM 与 Diff 算法

Q什么是虚拟 DOM?为什么要用?
虚拟 DOM = 用 JS 对象描述真实 DOM

为什么用:直接操作真实 DOM 很慢(引起重排重绘)。先用 JS 对象算出差异(Diff),最后一次性更新真实 DOM,减少 DOM 操作次数。

类比:直接改 DOM = 每改一处就搬一次家;虚拟 DOM = 先在纸上规划好改动,最后一次性搬完。
QVue 的 Diff 算法是怎么工作的?
核心:同层比较 + 双端对比

1. 只比较同一层级(不跨层比较)
2. Vue 2:双端 Diff(头头、尾尾、头尾、尾头四种对比)
3. Vue 3:快速 Diff(先头尾去同,再处理中间乱序部分,用最长递增子序列优化移动)

key 的作用:Diff 时用 key 判断"这个节点是新的还是原来就有的",有 key 就能复用,没 key 就只能按顺序比。

⑥ Vue 2 vs Vue 3 核心区别

对比Vue 2Vue 3
响应式Object.definePropertyProxy
API 风格Options API(data/methods/computed)Composition API(setup + ref/reactive)
生命周期beforeCreate/created/...setup/onMounted/...
多根节点❌ 不支持✅ Fragment 支持
Teleport✅ 传送门组件
Suspense✅ 异步组件 loading
性能打包减小 40%+,渲染快 50%+
TypeScript支持弱原生支持

⑦ 15 道高频面试速答

1Vue 3 的 Proxy 比 Vue 2 的 defineProperty 好在哪?
① 能监听新增属性(defineProperty 不行,要 $set);② 能监听数组下标修改;③ 懒代理(访问到才代理子属性),初始化更快;④ Proxy 是 ES6 原生 API,性能更好。
2computed 为什么有缓存?
computed 内部用 dirty 标记。依赖变了标记 dirty=true,下次访问才重新计算。依赖没变 dirty=false,直接返回缓存值。这就是"依赖不变不重算"。
3Vue 组件 data 为什么必须是函数?
组件可能被复用多次(多个实例)。如果是对象,所有实例共享同一个 data 引用 → 一个改了全跟着变。用函数每次返回新对象,保证每个实例有独立的 data。
4v-model 的原理是什么?
v-model 是语法糖,等价于 :value="text" @input="text = $event.target.value"。Vue 3 中组件 v-model 等价于 :modelValue + @update:modelValue
5keep-alive 是干什么的?
缓存不活动的组件实例。组件切换时不销毁,保留状态(表单输入、滚动位置)。有 include/exclude/max 三个属性。缓存的组件会触发 onActivated/onDeactivated 而不是 onMounted/onUnmounted。
6Vue 3 的 setup 语法糖(script setup)有什么好处?
① 不用写 export default 和 setup 函数;② 顶层声明的变量自动暴露给模板;③ 组件导入后直接用,不用注册;④ 更好的 TypeScript 类型推导;⑤ 编译后性能更好。
7defineProps 和 defineEmits 是什么?
Vue 3 的编译宏(只在 script setup 里用)。defineProps 声明接收的 props,defineEmits 声明触发的事件。不需要 import,编译时自动处理。
8provide/inject 和 Pinia 有什么区别?
provide/inject 是组件树内的依赖注入,适合祖孙传值,但不是响应式的(除非传 ref)。Pinia 是全局状态管理,响应式 + DevTools 支持 + 持久化。跨多层组件共享状态用 Pinia 更好。
9Vue 怎么做权限控制(按钮级别)?
① 自定义指令 v-permission:检查用户权限,无权限则移除元素;② v-if + 权限判断函数;③ 封装权限按钮组件。推荐自定义指令,最优雅。
10Vue 的 template 是怎么变成真实 DOM 的?
三步:① 编译:template → render 函数(AST 解析 → 优化 → 生成代码);② 渲染:render 函数执行 → 生成虚拟 DOM(VNode);③ 挂载:VNode → 真实 DOM。数据变了重新执行 render → 新旧 VNode Diff → 更新真实 DOM。
11Vue 3 的 Teleport 是干什么的?
传送门——把组件渲染到 DOM 树的其他位置(而不是当前位置)。典型场景:弹窗/Modal/Notification 渲染到 body 下,避免被父组件的 overflow:hidden 或 z-index 影响。
12watch 和 watchEffect 的区别?
watch:要明确指定监听哪个数据,可以拿到新旧值,默认不立即执行。watchEffect:自动收集依赖(用了什么就监听什么),立即执行一次,拿不到旧值。
13Vue 怎么优化性能?
① v-show 替代频繁切换的 v-if;② v-for 用唯一 key;③ 大列表用虚拟滚动;④ computed 缓存计算;⑤ keep-alive 缓存组件;⑥ 路由懒加载;⑦ 图片懒加载;⑧ 防抖节流。
14Pinia 比 Vuex 好在哪?
① 没有 mutations(直接改 state);② 多 store 平级管理不用 modules;③ TypeScript 原生支持;④ 体积更小(4KB vs 10KB);⑤ API 更简洁。
15SSR(服务端渲染)在 Vue 里怎么做?
用 Nuxt 3(Vue 官方推荐的 SSR 框架)。服务端把组件渲染成 HTML 字符串返回给浏览器,用户首屏直接看到内容(不用等 JS 加载)。好处:SEO 友好 + 首屏快。
速记口诀:Vue3用Proxy / ref基本reactive对象 / v-if真删v-show隐藏 / computed缓存watch做事 / v-for必加key / nextTick等DOM / keep-alive缓存组件