面试八股文 ——Vue 篇

Estimated reading: 3 minutes 13 views

引言💭

总结最近面试中碰到的Vue考点。

一、Vue 3 的常用 API

refreactive

  • ref:用于创建基本数据类型(如字符串、数字、布尔值等)的响应式引用,通过 .value 访问和修改数据。
  const count = ref(0); // 基本类型响应式数据
  • reactive:用于创建对象或数组的响应式数据,直接对对象进行响应式代理,可直接通过属性名访问和修改。
  const user = reactive({ name: 'Alice', age: 25 }); // 对象响应式数据

computed

  • 用于创建计算属性,基于依赖的响应式数据进行缓存,仅在依赖数据变化时重新计算。
  const doubleCount = computed(() => count.value * 2); // 计算属性示例
  • 适用场景:衍生数据计算(如表单校验、动态标题)。

watch

  • 用于监听响应式数据的变化,执行副作用操作(如异步请求、数据存储)。
  watch(count, (newVal, oldVal) => { /* 数据变化时执行 */ }); // 监听示例
  • 适用场景:异步操作、复杂副作用逻辑。

生命周期函数(组合式 API)

  • onMounted:组件挂载完成后执行(替代 Vue 2 的 mounted)。
  • onUpdated:组件更新完成后执行(替代 Vue 2 的 updated)。
  • onUnmounted:组件卸载后执行(替代 Vue 2 的 destroyed)。

defineComponent

  • 用于定义组件,支持组合式 API 和 TypeScript 类型推导,增强可读性和类型安全。
  import { defineComponent } from 'vue';
  export default defineComponent({ /* 组件配置 */ });

provideinject

  • 跨层级组件通信方案:父组件通过 provide 提供数据,子组件通过 inject 注入获取。
  // 父组件
  provide('theme', 'dark'); 
  // 子组件
  const theme = inject('theme'); 

nextTick

  • 在 DOM 更新后执行回调,确保获取更新后的 DOM 状态。
  this.$nextTick(() => { /* DOM 更新后操作 */ });

useContext

  • 获取当前组件的上下文,适用于函数式组件中访问 Vue 上下文信息。

二、refreactive 的区别

特性refreactive
适用类型基本数据类型(string/number等)对象/数组
访问方式通过 .value 访问直接通过属性名访问
示例const num = ref(10);const obj = reactive({ a: 1 });

三、computedwatch 的区别

特性computedwatch
核心作用缓存计算结果,返回衍生数据监听数据变化,执行副作用
触发时机依赖数据变化时自动执行监听数据变化时手动触发
适用场景表单校验、动态标题等API 请求、数据提交等异步操作

四、Vue 2 的 mixin 和 Vue 3 的 hooks 的对比

特性mixin(Vue 2)hooks(Vue 3)
逻辑复用通过混入组件选项实现通过组合式函数实现
命名冲突可能引发冲突(共享组件选项)按函数作用域隔离,无冲突
维护性大型项目中逻辑复杂难追踪按功能拆分,可组合性强

五、v-ifv-for 的使用及 key 的作用

  • v-if:条件渲染元素,条件为假时从 DOM 中移除元素,适合不频繁切换场景。
  • v-for:循环渲染列表,需搭配唯一 key(标识节点唯一性),提升虚拟 DOM Diff 效率。
  <ul>
    <li v-for="item in list" :key="item.id">{{ item.name }}</li>
  </ul>

六、Vue 3 组件生命周期及替代 API

Vue 2 生命周期Vue 3 组合式 API触发时机
mountedonMounted组件挂载到 DOM 后
updatedonUpdated组件数据更新并渲染后
beforeDestroyonBeforeUnmount组件卸载前
destroyedonUnmounted组件卸载后

七、Vue 2 与 Vue 3 的核心区别

特性Vue 2Vue 3
响应式原理Object.defineProperty(不支持数组索引/嵌套对象)Proxy(支持数组/嵌套对象,性能更优)
API 风格选项式(data/methods 等)组合式(setup+Hook,逻辑复用性强)
TypeScript 支持需额外配置内置类型推导,原生支持 TS
状态管理官方推荐 Vuex官方推荐 Pinia(API 更简洁)
虚拟 DOM 性能中等优化更快的 Diff 算法,大型应用性能提升

八、Vue 2 与 Vue 3 响应式系统的区别

  • Vue 2:基于 Object.defineProperty,需遍历对象属性,无法检测数组索引变更和嵌套对象深层变化。
  • Vue 3:基于 Proxy,直接代理整个对象,支持数组/嵌套对象的响应式追踪,性能更高。

九、Vue 组件通信方式

1. 父子组件通信

  • 父→子:通过 props 传递数据。
  <!-- 父组件 -->
  <child-component :message="parentMsg" />
  • 子→父:通过 $emit 触发事件。
  // 子组件
  this.$emit('update', childMsg); 

2. 跨层级通信

  • provide/inject:祖先组件提供数据,后代组件注入获取(适用于多层嵌套)。
  • 状态管理库:使用 Vuex/Pinia 管理全局状态(适用于复杂场景)。

3. 兄弟组件通信

  • 通过共同父组件中转数据,或使用全局事件总线(Vue 3 不推荐)。

十、Vuex 与 Pinia 的区别

特性VuexPinia
适用版本Vue 2.xVue 3+
API 风格选项式(mutations/actions组合式(函数式,支持 Hook)
TypeScript需手动声明类型内置类型推导,TS 友好
状态修改需通过 commit/dispatch直接修改响应式状态
持久化需手动实现支持插件(pinia-plugin-persistedstate

十一、选项式 API 和组合式 API 的区别

特性选项式 API组合式 API
逻辑组织按组件选项(data/methods)组织按功能函数(setup+Hook)组织
逻辑复用通过 mixin 实现通过 hooks 函数实现
可维护性大型项目中逻辑可能碎片化按功能拆分,可维护性更高
适用场景中小型项目,快速上手复杂/大型项目,逻辑复用需求高

十二、v-showv-if 的区别

特性v-showv-if
渲染机制通过 display: none 控制显隐条件为假时完全移除 DOM元素
性能切换频繁时性能更优(无需销毁重建)初次渲染性能较低(涉及 DOM 销毁)
适用场景高频切换(如按钮显隐)低频切换(如权限控制)

十三、虚拟 DOM 与 Diff 算法

  • 虚拟 DOM:用 JavaScript 对象模拟真实 DOM 结构,数据变更时先更新虚拟树,再批量同步到真实 DOM,减少直接操作 DOM 的开销。
  • Diff 算法:对比新旧虚拟 DOM 树,仅更新变化的节点,通过 key 标识节点唯一性,提升更新效率。

十四、v-bindv-model

  • v-bind:单向绑定 HTML 属性或组件特性。
  <a :href="url">链接</a> <!-- 动态绑定 href 属性 -->
  • v-model:双向绑定表单元素值(如 input/textarea),自动同步数据与视图。
  <input v-model="text" /> <!-- 双向绑定输入框值 -->

十五、Vue 3 的响应式劫持(Proxy)

  • Vue 3 使用 Proxy 替代 Vue 2 的 Object.defineProperty,实现对对象的响应式代理。
  • 优势
  • 支持数组索引变更和嵌套对象深层响应式。
  • 性能更优,拦截操作更全面(如属性删除、数组长度变化)。

十六、Vue 的插槽(Slot)

1. 默认插槽

  • 父组件内容插入子组件 <slot> 位置。
  <!-- 父组件 -->
  <child-component>
    <p>父组件内容</p>
  </child-component>
  <!-- 子组件 -->
  <template><slot></slot></template>

2. 具名插槽

  • 父组件通过 v-slot:name 指定插入位置。
  <!-- 父组件 -->
  <child-component>
    <template v-slot:header><h1>头部</h1></template>
  </child-component>
  <!-- 子组件 -->
  <template><slot name="header"></slot></template>

3. 作用域插槽

  • 子组件向插槽传递数据,父组件可访问子组件状态。
  <!-- 子组件 -->
  <slot :message="childMsg">默认内容</slot>
  <!-- 父组件 -->
  <template v-slot:default="slotProps">
    {{ slotProps.message }}
  </template>

十七、Vue 响应式追踪机制

  • 依赖收集:组件渲染时读取数据,将组件与数据建立关联。
  • 更新机制:数据变化时,触发关联组件重新渲染(基于 Proxy 的拦截操作)。

十八、Vue SSR(服务器端渲染)原理

  • 通过服务器预渲染组件为 HTML,发送给客户端,提升 SEO 和首屏加载性能。
  • 核心 API
  • createApp:创建 Vue 应用实例。
  • renderToString:将应用渲染为 HTML 字符串。

十九、Pinia 数据存储方式

  • 默认存储:状态存储在内存中,页面刷新会丢失。
  • 持久化存储:通过插件 pinia-plugin-persistedstate 存入 localStorage/sessionStorage
  import { createPinia } from 'pinia';
  import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
  const pinia = createPinia();
  pinia.use(piniaPluginPersistedstate); // 启用持久化插件

二十、Vue Router 模式对比

模式原理URL 示例特点
hash通过 URL 哈希值(#)路由https://a.com/#/home兼容性好,URL 含 #,无需服务端配置
history使用 HTML5 History APIhttps://a.com/homeURL 简洁,需服务端配置回退到 index.html
abstract适用于非浏览器环境(如 Node)无实际 URL 对应用于 SSR 等场景

二十一、状态管理库适用场景

  • 多组件共享状态(如用户登录状态、购物车数据)。
  • 状态变化复杂,需集中管理和追踪。
  • 跨页面/视图共享状态,避免组件间多层传递。

二十二、动态路由实现方式

  • 路由参数:通过 :param 定义动态参数(如 /user/:id),通过 $route.params.id 访问。
  • 懒加载组件:动态导入组件,减少初始加载体积。
  const User = () => import('./views/User.vue'); // 路由懒加载
  • 导航守卫:通过 beforeEnter 钩子在路由进入前加载数据。

二十三、Vue 3 发布-订阅模式

  • 基于 Proxy 实现响应式系统:数据变化时,Proxy 触发依赖收集的订阅者(组件/函数)重新渲染或执行回调。

二十四、keep-alive 缓存组件

  • 作用:缓存不活动组件,避免重复渲染,提升性能。
  • 用法
  <keep-alive include="ComponentA"> <!-- 缓存指定组件 -->
    <router-view></router-view>
  </keep-alive>
  • 属性
  • include:指定缓存的组件名称或正则。
  • exclude:指定不缓存的组件名称或正则。

二十五、Vue 懒加载实现方式

  • 路由级懒加载:动态导入组件(() => import('路径'))。
  • 组件级懒加载:使用 defineAsyncComponent 定义异步组件。
  import { defineAsyncComponent } from 'vue';
  const AsyncComponent = defineAsyncComponent(() => import('./Async.vue'));

二十六、Vue 打包配置要点

  • 代码分割:利用动态导入(import())实现按需加载。
  • 资源优化:压缩图片、字体,移除未使用代码(Tree Shaking)。
  • 环境变量:通过 process.env.NODE_ENV 区分开发/生产环境,配置不同打包策略。
  • 性能优化:开启 Gzip 压缩,使用 CDN 引入第三方库。

二十七、Vue 的核心优点

  1. 易学易用:语法简洁,文档友好,入门门槛低。
  2. 高性能响应式:基于 Proxy 的响应式系统,高效追踪数据变化。
  3. 组件化开发:便于复用和维护,适合构建大型应用。
  4. 灵活性强:支持选项式与组合式 API,适应不同项目规模。

二十八、nextTick 的作用

  • 场景:在数据更新后,需操作最新 DOM 时使用(如获取更新后的元素尺寸)。
  • 原理:等待 Vue 异步更新队列执行完毕,确保 DOM 已渲染完成。
  this.count = 10; // 修改数据
  this.$nextTick(() => {
    console.log(this.$refs.div.clientWidth); // 获取更新后的 DOM 尺寸
  });

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注