基础原理
Vue
渐进式框架的核心机制与生态。核心能力:响应式原理、组件化、生命周期、路由、状态管理。
Vue 面试常考两件事:1) 机制原理(响应式、虚拟 DOM、编译优化);2) 实战踩坑(为什么 data 是函数、nextTick 为什么不能同步读 DOM)。把原理 + 场景一起说才有说服力。
| 维度 | 组件 (Component) | 插件 (Plugin) |
|---|
| 作用 | 构建 UI 片段 | 扩展 Vue 全局功能 |
| 目标 | App.vue | Vue 本身 |
| 注册 | 局部 / 全局 | app.use(plugin) |
| 编写形式 | .vue 文件 | 暴露 install 方法 |
| 功能 | Vue 2 写法 | Vue 3 写法 |
|---|
| 全局属性/方法 | Vue.prototype.$xxx | app.config.globalProperties.$xxx |
| 全局组件 | Vue.component() | app.component() |
| 全局指令 | Vue.directive() | app.directive() |
| provide/inject | 手动实现 | app.provide() 原生支持 |
Vue 3 插件注册必须在 app.mount() 之前,否则不生效。
| 钩子 | 可访问 data | 可操作 DOM | 适用场景 |
|---|
created | 是 | 否 | 数据请求、初始化 |
mounted | 是 | 是 | DOM 操作、第三方库初始化 |
updated | 是 | 是 | 操作更新后的 DOM |
beforeDestroy | 是 | 是 | 清理定时器、移除监听(最重要) |
| Options API | Composition API | 适用场景 |
|---|
beforeMount | onBeforeMount | 最后的数据修改 |
mounted | onMounted | DOM 操作、第三方库初始化 |
beforeUnmount | onBeforeUnmount | 清理资源(最重要) |
unmounted | onUnmounted | 清理完成的通知 |
- 首次进入:
created → mounted → activated
- 再次进入:
activated(不经过 created/mounted)
- 失活:
deactivated(不经过 destroy)
- 根实例:data 可以是对象(单例,不复用)
- 组件:data 必须是函数(防止多个实例共享同一引用)
组件复用时,如果 data 是对象,所有实例引用同一份数据 → 数据污染。函数每次返回新对象,保证独立性。
- 初始化时遍历
data 的每个属性,添加 getter/setter
- 无法监听新增属性 → 需要
Vue.set()
- 无法监听 delete → 需要
Vue.delete()
- 数组需重写
push/pop/splice 等方法
- 代理整个对象,拦截所有操作
- 自动监听新增属性和删除操作
- 惰性代理:访问到哪层才代理哪层
- 原生支持数组索引和
length 变化
数据读取 (get)
↓
track(target, key) — 收集 effect 到依赖 Map
↓
数据修改 (set)
↓
trigger(target, key) — 找到并执行依赖中的 effect
↓
组件重新渲染 / computed 重新计算 / watch 回调
| 特性 | ref | reactive |
|---|
| 适用类型 | 基础 + 引用 | 仅对象 |
| 访问方式 | .value | 直接访问属性 |
| 替换整体值 | 支持 | 不支持(丢失代理) |
| 解构 | 安全 | 丢失响应式 |
Vue 3.2+ 官方推荐优先使用 ref:统一 .value 语法,无解构丢失问题,适合整体替换。
| 维度 | v-if | v-show |
|---|
| 控制 | 添加/删除 DOM | display: none |
| 初始渲染 | 条件为真才渲染 | 总是渲染 |
| 切换开销 | 高(重建 DOM) | 低(切换样式) |
| 适用场景 | 条件很少变化 | 频繁切换 |
| 生命周期 | 触发 | 不触发 |
| 版本 | 优先级 | 说明 |
|---|
| Vue 2 | v-for > v-if | 先遍历再判断 |
| Vue 3 | v-if > v-for | 先判断再遍历 |
不要在同一元素上使用 v-if 和 v-for。用 computed 过滤列表或将 v-if 移到外层。
Vue 的响应式更新是异步批处理的——数据变化后不会立即更新 DOM。
msg.value = 'Vue3 NextTick!'
console.log(box.value?.textContent) // 可能是旧值
nextTick(() => {
console.log(box.value?.textContent) // 确保拿到新值
})
- 修改数据后读取更新后的 DOM
v-if 创建元素后初始化第三方库
- 动态显示输入框后设置焦点
| 方式 | Vue 2 | Vue 3 | 核心差异 |
|---|
| 父 → 子 | props | defineProps | TS 类型推导更强 |
| 子 → 父 | $emit | defineEmits | 需提前声明 |
| 双向绑定 | v-model + .sync | v-model(多个) | 更统一 |
| 事件总线 | EventBus | mitt | Vue3 移除实例事件方法 |
| 跨级状态 | Vuex | Pinia | 更轻量,TS 原生 |
| 跨级注入 | provide/inject | ref/reactive 响应式 | 自动响应式 |
| 获取子实例 | $refs | ref + defineExpose | 需显式暴露 |
| 维度 | hash 模式 | history 模式 |
|---|
| URL 样式 | http://xxx/#/path | http://xxx/path |
| 原理 | hashchange 事件 | pushState/replaceState |
| 服务器配置 | 无需 | 需配置(否则刷新 404) |
| SEO | 不利 | 友好 |
| 类型 | 守卫 |
|---|
| 全局 | beforeEach / beforeResolve / afterEach |
| 路由独享 | beforeEnter |
| 组件内 | beforeRouteEnter / beforeRouteUpdate / beforeRouteLeave |
| 特性 | Vuex | Pinia |
|---|
| Mutation | 必须有,同步修改 | 已移除,Action 统一处理 |
| 模块化 | 嵌套 modules | 平铺独立 store |
| TS 支持 | 较弱 | 原生支持 |
| 动态注册 | 需手动 | 默认动态 |
- State:状态数据
- Getter:派生状态
- Action:同步 + 异步操作(不再区分 mutation)
| 优化方向 | 方案 |
|---|
| 减小入口体积 | 路由懒加载 |
| 静态资源缓存 | HTTP 缓存 + Service Worker |
| UI 框架按需 | Tree Shaking / 自动导入 |
| 图片优化 | WebP / 懒加载 / 响应式图片 |
| GZip 压缩 | Nginx / CDN 开启 |
| SSR | 服务端渲染首屏 |
| 模式 | Vue 应用 | 重要程度 |
|---|
| 观察者模式 | 响应式系统、watch、computed | 核心 |
| 代理模式 | Proxy 响应式、ref | 核心 |
| 组合模式 | 组件树、插槽 | 核心 |
| 工厂模式 | createApp、h 函数 | 重要 |
| 策略模式 | v-if/v-show、过渡动画 | 重要 |
| 发布订阅 | 事件总线、mitt | 重要 |
| 单例模式 | Router、Store | 一般 |