Vue 前端面试题(含答案)大全 v2025

Vue 前端面试题(含答案)大全 v2025

覆盖 Vue2/3 核心、Composition API、响应式原理、组件通信、指令、路由与状态管理(Vuex/Pinia)、性能优化、SSR/Nuxt、TypeScript、构建工具(Vite/Webpack)、测试、安全与可访问性、工程化与最佳实践。示例代码默认以 Vue 3 + Vite + <script setup> 为主,并注明 Vue 2 差异。


一、基础与生态

1. 什么是 Vue?与 React、Angular 的主要区别?

Vue 是渐进式前端框架,主打视图层 + 生态解耦(路由、状态管理按需选)。对比:React 函数式、JSX 心智;Angular 一体化、强约束;Vue 模板/指令友好、学习曲线平缓,Composition API 兼具灵活与组织性。

2. Vue2 与 Vue3 的核心变化?

  • 响应式:Object.defineProperty → Proxy(更好覆盖新增/删除属性、数组下标等)。
  • API:Options API → Composition API;新增 <script setup>、Teleport、Fragments。
  • 构建:官方推荐 Vite;Tree-shaking 更友好;性能/体积优化。
  • TS 友好度显著提升;自定义渲染器/内部架构重写(monorepo)。

3. 什么是渐进式框架?

可从小到大逐步引入能力:仅视图层 → 加上 Vue Router → 加上 Pinia/Vuex → SSR/Nuxt。

4. 模板语法与 JSX 的取舍?

模板({``{}} + 指令)表达 UI 更直观;JSX 灵活、可与 TS 深度结合。Vue 3 两者都支持,按团队偏好与场景选择。

5. 单文件组件(SFC)的组成?
<template> + <script>(或 <script setup>)+ <style scoped>,可加 <style module><style lang="scss"><script lang="ts">


二、响应式与渲染机制

6. Vue3 响应式如何实现?

基于 Proxy 拦截 get/set/has/deleteProperty,依赖收集(track)与触发(trigger)驱动 effect 重新执行,最小化更新。

7. 依赖收集发生在何时?

首次访问响应式数据(get)时在当前活跃 effect 上收集;数据变更(set)时精确触发相关 effect

8. refreactive 区别?
ref 包装原始值或对象(通过 .value 访问);reactive 仅用于对象/数组/Map/Set 等。模板中 ref 会自动解包。

9. 何时需要 toRef / toRefs

reactive 对象的属性以 ref 形式暴露,防止解构丢失响应性。

10. shallowRef / shallowReactive 用途?

只追踪顶层变化,适用于大型不可变数据/第三方实例(如图表对象)以减少开销。

11. 为何需要 markRawtoRaw
markRaw 标记对象不被代理;toRaw 获取原始对象,常用于与非响应式库交互或性能优化。

12. computedwatch 区别与使用时机?
computed 有缓存,适用于派生状态;watch 适合副作用(请求、日志)。watchEffect 会立即执行并追踪内部依赖。

13. nextTick 的作用?

等待下一轮 DOM 更新后执行回调,常用于依赖更新后 DOM 的操作(测量、滚动)。

14. Vue2 中变更检测的坑点?

不能检测对象属性新增/删除、数组通过索引修改等;需 Vue.set/this.$set 或替换为新数组。Vue3 已无此限制。

15. Diff 策略概览?

Vue 使用基于 key 的最小化 DOM 变更;Vue3 重写了核心算法,支持 Fragment/Teleport,diff 更快更小。


三、Composition API / <script setup>

16. 为什么引入 Composition API?

解决 Options API 在大型组件里逻辑分散(data/methods/computed 分段)的痛点,提升可复用性与类型推断。

17. 常用 API?
ref/reactive/computed/watch/watchEffect/onMounted/onUnmounted/provide/inject/getCurrentInstance 等。

18. <script setup> 的优势?

更少样板;顶层变量直接对模板可见;自动注册 defineProps/defineEmits/defineExpose;编译期优化。

19. defineProps / defineEmits / withDefaults 用法?

<script setup> 中声明 props/事件与默认值:

vue 复制代码
<script setup lang="ts">
const props = withDefaults(defineProps<{ size?: 'sm'|'md'|'lg'; count: number }>(), { size: 'md' })
const emit = defineEmits<{ (e:'update:count', v:number):void }>()
</script>

20. 多组件复用逻辑如何组织?

抽成 composable(useXxx.ts),输出状态与方法;配合依赖注入(provide/inject)实现跨层级共享。

21. exposedefineExpose 何用?

显式暴露子组件方法给父组件通过 ref 调用,避免暴露全部实例。

22. 在 <script setup> 如何获取组件实例?
const inst = getCurrentInstance()(谨慎使用,仅在需要访问 appContext/plugins 时)。


四、模板与指令

23. 常见指令及场景?
v-bindv-onv-if/else/else-ifv-showv-forv-modelv-slotv-htmlv-memo(Vue3.3+)。

24. v-if vs v-show
v-if 条件渲染(销毁/重建,首屏更省);v-show 仅切换 display(频繁切换更优)。

25. v-for 必须加 key 吗?

建议总是加稳定唯一的 key,帮助 diff 减少误复用,提高性能与正确性。

26. v-model 在 Vue3 的变化?

支持多 v-model、自定义参数(v-model:title),事件名为 update:modelValue;可用 defineModel(3.4+)简化双向绑定。

27. 具名插槽与作用域插槽?
<slot name="header"/> 具名;作用域插槽通过 v-slot="slotProps" 传值,由父读取子提供的数据。

28. v-html 风险?

容易引入 XSS,仅用于可信内容,并做好服务端过滤/转义。

29. 条件与循环混用反模式?

在同一元素上 v-if+v-for 会先循环再判断,建议外层包容器或用计算属性过滤数据。


五、组件通信

30. 父子通信?

父→子:props;子→父:emit;双向:v-model/defineModel
31. 兄弟通信?

通过父中转、事件总线(小型场景)或状态管理(Pinia/Vuex)。
32. 跨层级通信?
provide/inject 共享,或使用状态库。
33. 全局事件总线是否推荐?

仅限极小项目或一次性原型;中大型项目更建议 Pinia/Vuex。


六、路由(Vue Router 3/4)

34. Hash 与 History 模式?

Hash 依赖 #,无需服务端配置;History 更优雅但需服务端回退到 index.html

35. 动态路由与路由守卫?

动态:addRoute/基于权限生成;守卫:beforeEach/afterEach,组件内 beforeRouteEnter 等。常用做鉴权、埋点。

36. 路由懒加载?
component: () => import('...'),结合分包策略提升首屏速度。

37. 路由传参与刷新丢失问题?
params 需命名路由并在路径中声明;或改用 query,或持久化到 store/localStorage。

38. 滚动行为控制?
scrollBehavior(to, from, savedPosition) 恢复滚动、锚点定位。


七、状态管理(Vuex / Pinia)

39. Pinia 与 Vuex 区别?

Pinia 轻量、TS 友好、与 Composition API 自然融合;Vuex 4 兼容 Vue3,但写法偏模板化。新项目推荐 Pinia。

40. Pinia 基本用法?

定义 store:

ts 复制代码
// stores/user.ts
import { defineStore } from 'pinia'
export const useUser = defineStore('user', {
  state: () => ({ token: '', profile: null as null | {id:string,name:string} }),
  actions: { login(t:string){ this.token=t } }
})

组件内:const user = useUser();支持持久化(插件)、跨页面共享。

41. 何时不需要全局状态?

仅页面局部使用的数据用组件状态即可,避免过度全局化。

42. 派生状态放哪里?

Pinia 可用 getters,或在组件用 computed,避免重复计算与副作用。


八、网络请求与数据流

43. 在何处发起请求?

常在 onMountedwatch(依赖变动)或路由钩子里;SSR 场景需在服务端预取并脱水。

44. 如何取消请求与避免竞态?

使用 AbortController/axios 取消;在 watch 返回清理函数;用请求标记避免旧响应覆盖新数据。

45. 接口错误统一处理?

封装 http 模块/拦截器;全局错误边界(onErrorCaptured)、路由守卫兜底到错误页。


九、生命周期(Vue3 对照 Vue2)

46. 关键钩子映射

  • beforeCreate/createdsetup
  • beforeMount/mountedonBeforeMount/onMounted
  • beforeUpdate/updatedonBeforeUpdate/onUpdated
  • beforeDestroy/destroyedonBeforeUnmount/onUnmounted
  • 新增:onActivated/onDeactivated(配合 KeepAlive)、onErrorCapturedonRenderTracked/Triggered(调试)。

47. KeepAlive 使用?

缓存动态组件/路由组件状态,提高切换性能;配合 include/excludemax 控制缓存范围。


十、性能优化

48. 列出 10 条常见优化手段

  1. 路由与组件懒加载 2) 拆包/代码分割 3) 使用 defineAsyncComponent 4) 稳定 key 5) 避免在模板中执行重计算(用 computed) 6) v-memo/shallowRef 控制渲染 7) 大列表虚拟滚动 8) 图片懒加载/预设尺寸 9) SSR/预渲染 10) 生产环境关闭 devtool 与 verbose 日志。

49. 大列表如何优化?

虚拟列表(Vue Virtual Scroller)、分片渲染(requestIdleCallback)、骨架屏、占位符。

50. 何时手动 cache/memo

纯函数且依赖不变、渲染昂贵时;Vue3.3 v-memo 可缓存子树。

51. 避免不必要的响应式?

对静态大对象使用 markRaw;只在需要变更的点上使用 ref;使用 shallowRef 保存第三方实例。


十一、样式与 CSS 方案

52. scoped 的原理?

通过属性选择器(如 [data-v-xxx])限制样式作用域;注意深度选择需 :deep()

53. CSS Modules 与 scoped 区别?

Modules 通过哈希类名隔离,适合 TS/JS 驱动的样式组合;scoped 偏模板隔离。

54. 原子化/实用类(Tailwind)与传统 CSS?

原子类提高复用与一致性;传统 CSS 语义更清晰。混合使用需制定规范。


十二、表单与校验

55. 多层嵌套表单的可维护写法?

使用 v-model + defineModel、受控组件、vee-validate/@vueuse/form,组合式抽出校验逻辑。

56. 自定义表单组件如何与 v-model 对齐?

接收 modelValue、发出 update:modelValue;或 Vue3.4+ 使用 defineModel


十三、指令与插件

57. 自定义指令场景?

权限控制(置灰/隐藏)、懒加载、拖拽、点击外部、粘贴处理。
58. 指令生命周期钩子?
created/beforeMount/mounted/beforeUpdate/updated/beforeUnmount/unmounted

59. 如何封装全局插件?

暴露 install(app){ ... } 注册全局组件/指令/原型方法,配置通过 app.use(Plugin, options) 传入。


十四、SSR 与 Nuxt

60. SSR 的优缺点?

优:首屏快、SEO 友好;缺:服务端开销、状态同步复杂、缓存策略需要设计。

61. 基本思路?

服务端渲染 HTML → 客户端 hydrate 接管。数据需在服务端预取并注水(dehydrate/hydrate)。

62. Nuxt 关键点?

基于约定的文件结构、内置路由与数据获取(useAsyncData)、自动代码分割、服务器 API 路由。


十五、TypeScript 与类型推断

63. Vue3 对 TS 友好在哪里?
defineProps/defineEmits 泛型、<script setup lang="ts">、Pinia 原生类型、Volar 支持。

64. 如何为 emit 类型化?
const emit = defineEmits<{(e:'save', payload:{id:string}):void}>()

65. 组件公共 API 的类型导出?

使用 defineExpose 暴露方法类型,或导出 props/事件类型给外部复用。


十六、构建工具(Vite / Webpack)

66. 为什么推荐 Vite?

基于原生 ESM + esbuild 预构建,冷启动快;Rollup 生产构建,生态完善(Vue 官方插件)。

67. 常见 Vite 优化?

依赖预构建(optimizeDeps)、按需引入、分包(manualChunks)、CDN 外链、build.target/minify 设置。

68. 环境变量管理?
.env.[mode],通过 import.meta.env 访问;前缀 VITE_ 暴露给客户端。


十七、测试(Vitest/Jest、Cypress/Playwright)

69. 组件单测要点?

浅/深渲染、事件触发、异步更新(await nextTick())、快照、可访问性断言(aria-*)。

70. 如何 mock 网络与路由?

使用 msw/vi.mock;提供 routerpinia 测试实例;隔离副作用。

71. E2E 测试策略?

关键用户路径优先,稳定选择器(data-test),并发/重试、截图与视频留存。


十八、安全与可访问性

72. 常见前端安全问题?

XSS(v-html)、CSRF(同源策略/Token/双重 Cookie)、点击劫持(X-Frame-Options)、敏感信息泄露。
73. 如何防 XSS?

服务端转义、CSP、避免直接拼接 HTML、可信白名单、组件内谨慎使用 v-html

74. A11y 要点?

语义化标签、焦点管理、键盘可操作、对比度、aria-* 属性、为动态内容提供可达提示。


十九、国际化与多语言

75. vue-i18n 的基本用法?

创建 i18n 实例,<i18n-t> 富文本翻译,占位/复数处理;懒加载语言包与持久化语言偏好。


二十、工程化与最佳实践

76. 代码组织与命名规范?

按领域/路由分模块;组件 Base/App 前缀;composables 放 src/composables;样式变量集中化。

77. 提交规范与 CI?

Commitlint + Husky + Lint-Staged;ESLint + Prettier;CI 执行测试与构建。

78. 图标与资源管理?

Iconify/Unplugin Icons;图片资源使用 srcset 与构建期压缩。

79. 版本与发布?

语义化版本、变更日志、灰度发布/特性开关、Sentry 监控。

80. 常见代码味道?

胖组件、滥用全局状态、watch 里做业务堆叠、过多 any、硬编码 URL/常量。


二十一、经典代码题与场景题

81. 实现一个可复用的防抖/节流 composable

ts 复制代码
// useDebounce.ts
export function useDebounce<T>(value: T, delay = 300){
  const v = ref(value) as Ref<T>
  let t: number | undefined
  watch(() => value, (nv) => {
    clearTimeout(t)
    t = window.setTimeout(() => (v.value = nv), delay)
  })
  return v
}

82. 封装一个 useFetch

ts 复制代码
export function useFetch<T>(url: MaybeRef<string>){
  const data = ref<T | null>(null)
  const error = ref<unknown>(null)
  const loading = ref(false)
  const controller = ref<AbortController | null>(null)
  async function run(){
    loading.value = true
    controller.value?.abort()
    controller.value = new AbortController()
    try{
      const res = await fetch(unref(url), { signal: controller.value.signal })
      data.value = await res.json()
    }catch(e){ error.value = e }
    finally{ loading.value = false }
  }
  onMounted(run)
  return { data, error, loading, run, cancel: () => controller.value?.abort() }
}

83. 父子组件双向绑定(defineModel 版)

vue 复制代码
<!-- Child.vue -->
<script setup lang="ts">
const model = defineModel<string>()
</script>
<template>
  <input v-model="model" />
</template>

84. 大列表虚拟滚动的思路?

只渲染可视区 + 缓冲区,计算偏移量定位容器高度;监听滚动计算首尾索引。

85. 自定义指令:点击外部关闭

ts 复制代码
export const clickOutside = {
  beforeMount(el: any, binding: any){
    el.__handler__ = (e: MouseEvent) => {
      if(!el.contains(e.target)) binding.value(e)
    }
    document.addEventListener('click', el.__handler__)
  },
  unmounted(el: any){
    document.removeEventListener('click', el.__handler__)
  }
}

86. 路由鉴权示例

ts 复制代码
router.beforeEach((to, from, next) => {
  const user = useUser()
  if(to.meta.requiresAuth && !user.token) next({ name: 'login', query: { redirect: to.fullPath } })
  else next()
})

87. 错误边界捕获

ts 复制代码
onErrorCaptured((err, instance, info) => {
  console.error(err, info)
  return false // 向上传播
})

二十二、开放题(可扩展)

88. 设计一套组件库的技术方案

  • 技术栈:Vue3 + TS + Vite + Vitest + Playwright
  • 规范:按需加载、样式 tokens、图标方案、文档站(VitePress)
  • 质量:单测覆盖、视觉回归、a11y 校验、CI 发布(changeset)。

89. 业务中如何拆分"胖组件"?

识别职责并抽出 composables;数据获取/状态分离;呈现组件(presentational)与容器组件(container)分层。

90. 在微前端架构中接入 Vue 应用?

使用 qiankun/Module Federation;公共依赖外链;路由隔离与沙箱;状态通过事件总线或 shared store 同步。


二十三、Vue2 兼容与迁移

91. 迁移注意点

  • 过滤器(filters)移除:用计算属性/方法代替
  • $listeners/$attrs 合并行为变化;v-model 事件名变化
  • 插槽语法(slot-scopev-slot
  • 全局 API 迁移到 app.config.globalProperties/app.use()

92. 常见迁移策略

  • 先升级依赖与构建工具 → 消除警告 → 引入组合式重构复杂组件 → 单元测试保障回归。

二十四、杂项高频问答

93. teleport 用于什么?

将子树渲染到 DOM 的另一个位置,例如全局模态、悬浮层。

94. fragments 是什么?

多根节点组件支持;Vue2 需要包一层容器,Vue3 可直接返回数组模板。

95. 如何监听组件尺寸或元素可见?
ResizeObserverIntersectionObserver,配合 @vueuse/core(如 useElementSize)。

96. SSR 中如何避免水合不一致?

仅在客户端访问浏览器 API;使用 client-only/<Suspense>;确保初始数据一致。

97. 如何优雅处理权限按钮显示?

自定义指令或组件包裹,基于权限表判断;禁用与隐藏策略分离;审计埋点。

98. 如何处理长列表选择/勾选性能?

受控集合结构(Set),惰性渲染复选框;批量更新(事务化);虚拟滚动。

99. 如何定位响应式性能瓶颈?
onRenderTracked/Triggered 调试;性能面板采样;标记关键 computedwatch 的依赖图。

100. 你最常用的 Vue 工具库?为什么?
@vueuse/core(高质量 composables)、Pinia、Vue Router、VitePress、Iconify、UnoCSS/Tailwind、Vitest/Testing Library。


附录 A:面试速查清单(提纲)

  • Vue3 响应式:Proxy/track/trigger/effect;ref/reactive/computed/watch
  • 组件通信:props/emit/v-model/provide-inject/store
  • 路由:懒加载、守卫、动态路由、滚动恢复
  • 状态:Pinia vs Vuex;何时全局
  • 性能:分包、虚拟列表、v-memomarkRaw
  • SSR/Nuxt:hydrate、数据脱水、缓存
  • TS:defineProps/Emits 泛型,<script setup>
  • 工程化:Vite、ESLint/Prettier、CI、监控
  • 安全/A11y:XSS、CSP、aria

提示:根据岗位 JD,选择性深挖以上任意模块并准备代码 Demo(虚拟列表、指令、composable、路由鉴权、错误边界等)。

相关推荐
meichaoWen7 小时前
【Vue3】vue3的全面学习(一)
前端·javascript·学习
小猪努力学前端7 小时前
在 React + React Router v7 SSR 项目里做多端适配,我踩的两个坑
前端·react.js
q***d1737 小时前
React桌面应用开发
前端·react.js·前端框架
8***29317 小时前
解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域
java·前端·spring
0***147 小时前
React计算机视觉应用
前端·react.js·计算机视觉
Q***K557 小时前
React高级
前端·react.js·前端框架
c***97987 小时前
React语音识别案例
前端·react.js·语音识别
q***57747 小时前
WebSpoon9.0(KETTLE的WEB版本)编译 + tomcatdocker部署 + 远程调试教程
前端
Q***l6878 小时前
Vue增强现实案例
前端·vue.js·ar
十里-8 小时前
前端监控1-数据上报
前端·安全