Code前端首页关于Code前端联系我们

2022 Vue3 高频面试题全解析

terry 2天前 阅读数 29 #SEO
文章标签 Vue3;面试题

2022 年 Vue3 已成前端面试“必考点”,从核心原理到工程实践,问题覆盖越来越细,这篇文章把当年最火的 Vue3 面试题整理成问答,帮你理清逻辑、巩固知识~

Vue3 和 Vue2 核心区别有哪些?

Vue3 从底层到上层做了全方位重构,核心差异体现在这些维度:

  • 响应式原理:Vue2 靠 Object.defineProperty 拦截属性读写,但对数组下标/长度、对象新增属性“盲视”;Vue3 改用 Proxy 代理整个对象,能监听数组变化(不用重写 push/pop)、对象增删属性,还支持 Map/Set 等复杂结构。
  • 代码组织与复用:Vue2 依赖 Options API(data/methods 拆分),复杂组件逻辑分散、复用靠易冲突的 mixins;Vue3 的 Composition API(setup + ref/reactive)把相关逻辑“扎堆”,复用靠自定义 Hook(如封装请求的 useFetch),维护性拉满。
  • 性能优化:编译阶段做了静态提升(复用静态节点)、补丁标志(精准更新动态节点);运行时靠 Proxy 实现“懒响应式”(访问时才建立依赖),还支持 Tree-shaking(没用到的 API 不打包)。
  • 新特性补充:新增 Teleport(跨组件渲染)、Suspense(异步组件管理)、Fragment(多根节点),解决弹窗层级、异步加载状态难管理等痛点。

Composition API 相比 Options API 优势在哪?

这个问题考察对代码组织和工程化的理解,核心优势有三点:

  • 逻辑复用更丝滑:Options API 用 mixins 复用逻辑易冲突、难溯源;Composition API 把逻辑封装成自定义 Hook(如 useUserInfo 封装用户信息逻辑),组件按需引入,归属清晰。
  • 复杂组件易维护:若组件有“表单验证 + 数据请求 + 弹窗控制”等模块,Options API 里逻辑分散在 data/methods,看代码得来回跳;Composition API 能把同一功能的变量、方法“扎堆”写,维护时一眼定位。
  • TypeScript 更友好:Options API 里 this 类型难推导,给组件加类型注释麻烦;Composition API 中 ref/reactive 支持泛型(如 ref<number>(0)),配合 defineComponent 能自动推导 props/emits 类型,TS 报错更及时。

ref 和 reactive 怎么选?什么时候用哪个?

两者都是响应式工具,但适用场景不同:

  • ref:适合处理基本类型(string/number)或需重新赋值的对象const count = ref(0),修改用 count.value = 1;对象场景下,const user = ref({ name: '张三' }) 既支持改属性(user.value.name = '李四'),也支持重新赋值整个对象(user.value = { name: '王五' })。
  • reactive:专门处理对象/数组这类引用类型,且是“深层响应式”(嵌套对象也能监听),但要注意:reactive 对基本类型无效,且不能直接替换整个对象(如 const list = reactive([1,2,3]),直接 list = [4,5,6] 会丢失响应式)。

实际开发中,简单值用 ref,复杂对象/数组优先 reactive;若要解构 reactive 对象的属性并保持响应式,需用 toRefs(如 const { name, age } = toRefs(user),解构后 name.value 仍响应式)。

Vue3 响应式原理为啥用 Proxy 替代 Object.defineProperty?

得说清 Proxy 的核心优势:

  • 数组全监听:Vue2 监听数组需重写 push/pop 等方法,但对 arr[0] = 1(下标修改)、arr.length = 0(长度修改)检测不到;Proxy 能直接拦截数组所有操作,无需 hack。
  • 对象属性更灵活:Vue2 新增对象属性(如 obj.newKey = '新值')不触发更新,得用 $setProxy 能拦截 set 操作,新增属性自然响应。
  • 性能与扩展性Object.defineProperty 需遍历对象所有属性提前拦截,Proxy 是“懒代理”(访问时才建立依赖),初始化更快;且 Proxy 支持 Map、Set 等复杂结构,扩展性更强。

setup 函数里能访问 this 吗?为什么?

不能,因为 setup 执行时机在 beforeCreate 之前——组件实例(this 指向的对象)还没创建,thisundefined

若需访问 props/emit/slots,可通过 setup 的参数获取:第一个参数 props(已做响应式,不能解构后丢失响应式),第二个参数 context(包含 emit/slots/attrs),比如触发事件用 context.emit('change', value),访问 attrs 用 context.attrs

Teleport 组件是干啥的?实际项目咋用?

Teleport 是“传送门”,能把组件内部分内容渲染到组件外的指定 DOM 节点,最典型场景是弹窗(Modal):父组件若有 overflow: hiddenz-index 限制,弹窗易被截断或层级不够,用 Teleport 把弹窗内容渲染到 body,就能绕过父组件样式影响。

代码示例:

<template>
  <button @click="showModal = true">打开弹窗</button>
  <Teleport to="body"> <!-- 指定渲染到 body -->
    <div v-if="showModal" class="modal">
      <div class="content">我是弹窗内容</div>
    </div>
  </Teleport>
</template>

Suspense 组件怎么理解?适用场景?

Suspense 是 Vue3 处理异步组件加载状态的内置组件,能在等待异步组件加载时展示加载态,失败时展示错误态,需配合异步组件(如 defineAsyncComponent 定义的组件)或组件内异步逻辑(如 async setup)使用。

典型场景:页面分模块异步加载(如用户信息、订单列表组件),用 Suspense 统一管理状态:

<template>
  <Suspense>
    <template #default>
      <AsyncUser /> <!-- 异步组件 -->
      <AsyncOrder />
    </template>
    <template #fallback>
      <div>正在加载页面内容...</div> <!-- 加载中展示 -->
    </template>
  </Suspense>
</template>

还能结合错误边界(ErrorBoundary)处理加载失败,提升页面容错性。

Vue3 做了哪些性能优化?

Vue3 从“编译时 + 运行时”双向优化:

  • 编译阶段
    • 静态提升:提取不依赖响应式的静态节点(如纯文本、固定结构元素),复用虚拟 DOM 节点,减少创建开销。
    • 补丁标志(Patch Flag):给动态节点打标记(如文本插值标记为 1,class 变化标记为 2),更新时只处理带标记节点,精准更新。
    • 缓存事件处理函数:如 @click="handleClick" 编译后会被缓存,避免每次渲染新建函数。
  • 运行时
    • 响应式系统Proxy 替代 Object.defineProperty 后,初始化更快(懒代理)、监听更全面(数组、新增属性等)。
    • Tree-shaking:Vue3 基于 ESM 构建,没用到的 API(如不用 Keep-Alive 则不打包)会被摇掉,缩小体积。

Vue3 里怎么写自定义指令?和 Vue2 有啥不同?

Vue3 自定义指令的钩子函数和参数结构有变化:

  • 钩子变化:Vue2 是 bind、inserted、update、componentUpdated、unbind;Vue3 改为 created、beforeMount、mounted、beforeUpdate、updated、beforeUnmount、unmounted(更贴近组件生命周期)。

  • 示例(自动聚焦指令):

    // 全局注册
    app.directive('focus', {
      mounted(el) { // 元素挂载后执行
        el.focus()
      }
    })
    // 局部注册
    export default {
      directives: {
        focus: {
          mounted(el) {
            el.focus()
          }
        }
      }
    }

    模板中用 <input v-focus /> 即可,若需处理指令参数(如 v-focus="true"),可通过钩子参数 binding.value 获取。

Vue 状态管理用 Vuex 还是 Pinia?怎么选?

2022 年多数团队转向 Pinia(Vuex 团队成员开发,相当于“Vuex5 实验版”),优势明显:

  • 更轻量:体积远小于 Vuex,打包后对项目体积影响小。
  • API 更简洁:无需写 mutation(直接在 action 改状态),少一层心智负担;用 defineStore 即可创建 Store,写法更简单。
  • TypeScript 友好:内置 TS 支持,定义状态、操作时类型推导自然,无需额外配置。

新项目(尤其 TS 项目)优先选 Pinia;老项目(Vuex 写的)可继续用 Vuex 但逐步迁移;Vuex 仍在维护,但生态重心已向 Pinia 倾斜。

Vue3 对 TypeScript 的支持有啥提升?

Vue3 从框架层适配 TS,体验大幅提升:

  • 组合式API 天然适配ref/reactive 支持泛型(如 ref<number>(0)),定义对象时用接口更顺畅(如 const user = reactive<IUser>({ name: '...' }))。
  • defineComponent 自动推导:用 defineComponent 包裹组件后,TS 能自动推导 props/emits 类型,示例:
    export default defineComponent({
      props: {
        title: String
      },
      emits: ['change'],
      setup(props) {
        // props.title 会被推导为 string | undefined
      }
    })
  • JSX/TSX 更友好:Vue3 对 TSX 支持更完善,写函数式组件或复杂渲染逻辑时,类型提示更准确。

2022 年 Vue3 面试题围绕“新特性、底层原理、性能优化、生态工具、TS 支持”展开,吃透这些问题,不仅能应付面试,写代码也会更顺手~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门