跳转到内容

Vue 面试真题汇总

Vue 组件初始化的各个阶段都做了什么?

Section titled “Vue 组件初始化的各个阶段都做了什么?”

Vue 组件初始化主要分为创建阶段挂载阶段

创建阶段包括 beforeCreate(初始化组件实例基本属性、事件系统,此时无法访问 data、methods 等)和 created(完成数据观测、响应式系统建立、props 初始化,可访问组件数据但无法访问 DOM)。

挂载阶段包括 beforeMount(模板编译完成,生成虚拟 DOM,但真实 DOM 未创建)和 mounted(组件挂载到 DOM 完成,可访问真实 DOM 元素和子组件实例)。渲染函数首次调用发生在 beforeMountmounted 之间,此时会触发响应式变量的依赖收集,建立组件与响应式数据的依赖关系。

在 Vue3 组合式 API 中,setup 函数在所有生命周期钩子之前执行,响应式数据在 setup 中定义,但依赖收集要等到渲染函数执行时才开始。

Vue3相比Vue2有以下主要区别:

响应式系统:Vue2使用Object.defineProperty实现响应式,只能监听对象属性的变化,对数组和新增属性支持不好;Vue3使用Proxy实现,可以监听整个对象的所有操作,包括属性的增删改查。

组合式API:Vue2主要使用选项式API(data、methods、computed等),代码按选项类型分散;Vue3引入组合式API(setup函数),相关逻辑可以组织在一起,提高代码复用性和可维护性。

性能优化:Vue3在编译时进行了大量优化,如静态提升、补丁标记、树摇优化等,运行时性能比Vue2提升1.3-2倍,包体积减少约41%。

TypeScript支持:Vue3从底层用TypeScript重写,提供了更好的类型推导和类型安全,开发体验更佳。

生命周期变化:Vue3在组合式API中使用onMounted、onUpdated等钩子函数,替代了Vue2的mounted、updated等选项。

对比维度Vue2Vue3
响应式原理Object.definePropertyProxy
API风格选项式API组合式API + 选项式API
TypeScript支持需要额外配置原生支持
包体积较大减少41%
性能基准性能提升1.3-2倍

了解过Vue2的diff算法吗,能简单说说吗?

Section titled “了解过Vue2的diff算法吗,能简单说说吗?”

Vue2的diff算法是虚拟DOM更新的核心机制,主要采用双端比较策略来高效地找出新旧虚拟DOM树的差异。

核心流程

  1. 同层比较:只比较同一层级的节点,不跨层级比较,降低算法复杂度
  2. 双端比较:设置四个指针(旧头、旧尾、新头、新尾),进行四种比较方式:
    • 旧头 vs 新头:相同则直接复用
    • 旧尾 vs 新尾:相同则直接复用
    • 旧头 vs 新尾:相同则移动到尾部
    • 旧尾 vs 新头:相同则移动到头部
  3. key值查找:四种比较都失败时,通过key在旧节点中查找匹配节点
  4. 创建和删除:找不到匹配节点则创建新节点,剩余旧节点则删除

优势:通过双端比较能够快速处理常见的DOM操作场景(如列表头尾插入、反转等),避免不必要的节点移动,提高更新效率。

时间复杂度:理想情况下为O(n),最坏情况下为O(n²)。

说说 Vue2 和 Vue3 diff 算法的区别?

Section titled “说说 Vue2 和 Vue3 diff 算法的区别?”

Vue2和Vue3的diff算法在核心思路和优化策略上有显著差异:

Vue2 diff算法:采用双端比较策略,通过头头、尾尾、头尾、尾头四种方式进行节点比较。当四种比较都无法匹配时,会遍历旧节点列表查找相同key的节点。时间复杂度在最坏情况下为O(n²)。

Vue3 diff算法:引入了最长递增子序列算法,显著提升了性能。主要优化包括:

  • 静态标记:编译时标记动态节点,跳过静态节点的比较
  • 最长递增子序列:找出不需要移动的节点序列,减少DOM操作
  • 块级更新:将动态内容提取到Block中,只对变化的部分进行diff

性能对比:Vue3的diff算法在处理大量节点时性能提升明显,特别是在节点顺序变化较少的场景下,能够将时间复杂度优化到接近O(n)。

对比项Vue2Vue3
核心策略双端比较最长递增子序列
静态优化静态标记跳过
时间复杂度O(n²)接近O(n)
DOM操作次数较多显著减少

Vue主要通过Scoped CSSCSS Modules两种方式实现样式隔离:

Scoped CSS

  • <style scoped>标签中编写的样式会被自动添加唯一的属性选择器
  • 编译时为组件的每个元素添加data-v-xxx属性,样式选择器也会相应添加该属性
  • 实现原理:通过PostCSS插件在构建时转换CSS选择器,确保样式只作用于当前组件
  • 优点:使用简单,无需额外配置;缺点:会增加CSS选择器的特异性

CSS Modules

  • 通过<style module>启用,将CSS类名转换为局部作用域的唯一标识符
  • 类名会被编译成哈希值,避免全局污染
  • 在模板中通过$style.className的方式使用样式类
  • 优点:完全隔离,性能更好;缺点:使用相对复杂

深度选择器

  • 在Scoped CSS中使用:deep()::v-deep>>>穿透样式隔离
  • 用于修改子组件的样式,但要谨慎使用避免破坏封装性

全局样式

  • 使用:global()选择器或单独的<style>标签定义全局样式
  • 适用于重置样式、第三方组件样式覆盖等场景

Vue3 的组合式API相较于 Option API 有哪些优点?

Section titled “Vue3 的组合式API相较于 Option API 有哪些优点?”

组合式API相比选项式API具有以下显著优势:

逻辑组织更清晰

  • 选项式API按选项类型分散代码(data、methods、computed分离),相关逻辑被拆分到不同区域
  • 组合式API可以将相关的响应式数据、计算属性、方法组织在一起,提高代码的内聚性和可读性

更好的代码复用

  • 选项式API主要通过mixins实现复用,但存在命名冲突、来源不明确等问题
  • 组合式API通过自定义Hook(composables)实现逻辑复用,更加灵活且类型安全

更强的TypeScript支持

  • 选项式API在TypeScript中类型推导较弱,需要额外的类型声明
  • 组合式API提供完整的类型推导,IDE智能提示更准确,开发体验更佳

更灵活的逻辑抽象

  • 选项式API受固定结构限制,难以进行复杂的逻辑抽象
  • 组合式API可以根据业务需求自由组织代码结构,支持更复杂的逻辑封装

更好的Tree-shaking支持

  • 组合式API按需引入响应式API,未使用的功能可以被构建工具移除
  • 有助于减少最终打包体积
对比维度选项式API组合式API
逻辑组织按选项类型分散按功能逻辑聚合
代码复用mixins(有局限性)composables(更灵活)
TypeScript支持类型推导较弱完整类型推导
学习成本较低相对较高
适用场景简单组件复杂逻辑组件

能说下 Vue 是怎么实现双向绑定的吗?

Section titled “能说下 Vue 是怎么实现双向绑定的吗?”

Vue的双向绑定是通过响应式系统指令系统协同实现的,核心原理如下:

响应式数据劫持

  • Vue2:使用Object.defineProperty劫持对象属性的getter/setter,在getter中收集依赖,在setter中触发更新
  • Vue3:使用Proxy代理整个对象,可以监听属性的增删改查等所有操作

依赖收集与派发更新

  • 组件渲染时访问响应式数据,触发getter进行依赖收集,建立数据与组件的关联关系
  • 数据变化时触发setter,通知所有依赖该数据的组件重新渲染

v-model指令实现

  • v-model本质上是语法糖,等价于:value@input的组合
  • 表单元素变化时触发input事件,更新绑定的数据
  • 数据变化时通过响应式系统更新表单元素的value

双向绑定流程

  1. 数据到视图:数据变化 → 触发setter → 通知依赖 → 重新渲染 → 更新DOM
  2. 视图到数据:用户输入 → 触发事件 → 执行事件处理器 → 更新数据 → 触发响应式更新

关键组件

  • Observer:负责将数据转换为响应式对象
  • Dep:依赖收集器,管理依赖关系
  • Watcher:观察者,当数据变化时执行相应的更新操作
版本数据劫持方式优势局限性
Vue2Object.defineProperty兼容性好无法监听数组索引、对象新增属性
Vue3Proxy功能完整,性能更好IE不支持

平时项目中性能优化怎么做的,能简单说说吗?

Section titled “平时项目中性能优化怎么做的,能简单说说吗?”

Vue项目性能优化主要从以下几个维度进行:

组件层面优化

  • 使用v-memo缓存复杂的渲染结果,避免不必要的重新计算
  • 合理使用v-showv-if:频繁切换用v-show,条件渲染用v-if
  • 组件懒加载:使用defineAsyncComponent实现按需加载
  • 避免在模板中使用复杂表达式,改用计算属性

数据响应式优化

  • 使用shallowRefshallowReactive处理大型数据结构
  • 通过markRaw标记不需要响应式的对象
  • 合理使用readonly避免不必要的响应式转换
  • 大列表使用虚拟滚动技术

路由和代码分割

  • 路由懒加载:component: () => import('./Component.vue')
  • 按功能模块进行代码分割,减少首屏加载时间
  • 使用Suspense组件优化异步组件加载体验

构建优化

  • 开启Gzip压缩和资源压缩
  • 使用CDN加速静态资源加载
  • 图片懒加载和格式优化(WebP等)
  • 合理配置缓存策略

监控和分析

  • 使用Vue DevTools分析组件性能
  • 通过Performance API监控关键指标
  • 定期进行Bundle分析,识别体积过大的依赖
优化类型具体措施效果
渲染优化v-memo、计算属性减少重复计算
加载优化懒加载、代码分割提升首屏速度
数据优化shallow API、虚拟滚动降低内存占用
资源优化压缩、CDN、缓存减少网络传输