② 生命周期
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。
④ 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 里。
⑦ 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缓存组件