Skip to content

高级 Vue 面试题

Vue2 vs Vue3

1. 响应式原理的区别

Vue2

  • 使用 Object.defineProperty()
  • 无法监听对象新增/删除属性
  • 无法监听数组索引和 length 变化
  • 需要 $set/$delete 辅助方法

Vue3

  • 使用 Proxy 代理整个对象
  • 可以监听对象新增/删除属性
  • 可以监听数组索引和 length 变化
  • 支持 Map、Set、WeakMap、WeakSet

2. 性能优化

Vue3 性能提升

  • 源码体积减少 41%(Tree-shaking)
  • 初始化渲染快 55%,更新渲染快 133%
  • 内存占用减少 54%
  • 编译优化(静态提升、PatchFlag)

3. Composition API vs Options API

Composition API 优势

  • 逻辑复用更方便(自定义 Hook)
  • 代码组织更清晰(按功能而非选项类型)
  • TypeScript 支持更好
  • 更好的 Tree-shaking

响应式系统

1. Vue3 的依赖收集流程

  1. 创建 Proxy 代理对象
  2. getter 中收集依赖(track)
  3. setter 中触发更新(trigger)
  4. 使用 Effect 管理副作用

2. ref 和 reactive 的区别

  • ref:返回一个响应式引用对象,通过 .value 访问,适用于所有类型
  • reactive:返回一个响应式代理对象,只适用于对象类型

3. computed 和 watch 的区别

  • computed:基于依赖缓存,只有依赖变化才重新计算,有返回值
  • watch:监听数据变化执行回调,无返回值,支持深度监听和立即执行

虚拟 DOM 与 Diff

1. Vue 的 Diff 算法

采用双端 Diff

  1. 对比新旧节点列表的头部和尾部
  2. 通过 key 值寻找可复用节点
  3. 处理剩余节点

时间复杂度 O(n)。

2. key 的作用?

  • 帮助 Vue 识别节点身份
  • 提高 Diff 效率
  • 维持组件状态

注意:避免使用 index 作为 key,特别是在列表有增删操作时。

3. 静态提升 (Static Hoisting)

Vue3 编译优化:将静态节点提升到渲染函数外部,避免每次渲染时重新创建。

js
// 编译前
const _hoisted_1 = /*#__PURE__*/ createVNode('div', null, 'static text', -1 /* HOISTED */)

编译原理

1. Vue 模板编译流程

  1. 解析 (Parse):将模板字符串解析为 AST
  2. 转换 (Transform):对 AST 进行转换和优化
  3. 生成 (Generate):将 AST 生成渲染函数代码

2. PatchFlag 的作用

Vue3 在编译时为动态节点打上标记(PatchFlag),运行时只对比有标记的节点:

  • TEXT_CHILDREN:动态文本
  • CLASS:动态 class
  • STYLE:动态 style
  • PROPS:动态 props
  • FULL_PROPS:完全动态 props
  • HYDRATE_EVENTS:需要事件处理

源码相关

1. nextTick 原理

Vue 的异步更新策略:数据变化不会立即更新 DOM,而是将更新操作放入异步队列,在下一个 tick 统一执行。

实现方式优先级:Promise > MutationObserver > setImmediate > setTimeout

2. keep-alive 原理

  • 缓存组件实例,避免重复渲染
  • 使用 LRU 算法管理缓存
  • 提供 include/exclude/max 配置
  • 触发 activated/deactivated 生命周期

3. provide/inject 原理

  • 依赖注入机制
  • provide 提供数据,inject 注入数据
  • 数据不是响应式的,需要传入响应式对象
  • 用于跨层级组件通信

Vue Router

1. 路由模式

  • hash 模式:使用 URL hash,兼容性好,不需要服务端配置
  • history 模式:使用 HTML5 History API,URL 更美观,需要服务端配置 fallback

2. 导航守卫

  • 全局前置守卫:beforeEach
  • 全局解析守卫:beforeResolve
  • 全局后置钩子:afterEach
  • 路由独享守卫:beforeEnter
  • 组件内守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

3. 动态路由匹配

js
const routes = [{ path: '/user/:id', component: User }]

通过 $route.params.id 获取参数。

Pinia / Vuex

1. Pinia 相比 Vuex 的优势

  • 更简洁的 API
  • 完整的 TypeScript 支持
  • 支持多个 store
  • 模块化设计更简单
  • 支持服务端渲染
  • 体积更小(1KB)

2. Pinia 核心概念

  • State:仓库数据
  • Getters:计算属性
  • Actions:操作方法(支持异步)
  • $patch:批量修改状态
  • $reset:重置状态