35 道常见前端 Vue 面试题深度解析
Vue.js 作为当前主流的前端框架之一,其核心概念和生态组件是面试中的高频考点。本文整理了 35 道涵盖基础原理、组件通信、路由管理及性能优化的经典面试题,帮助开发者系统梳理知识体系。
1. 请讲述下 Vue 的 MVVM 的理解?
MVVM(Model-View-ViewModel)是一种设计模式,旨在将数据模型与视图表现层通过数据驱动进行分离。
- Model:代表数据模型,定义数据和业务逻辑。
- View:代表页面展示组件(DOM 展现形式),负责将数据转化为 UI。
- ViewModel:连接 Model 和 View 的桥梁,监听数据变化并控制视图行为,处理用户交互。
在 MVVM 架构下,View 和 Model 之间没有直接联系,而是通过 ViewModel 交互。双向数据绑定使得 View 的变化同步到 Model,Model 的变化也立即反应到 View,无需人为干涉。
2. Vue 的生命周期及理解?
Vue 实例从创建到销毁会经历一系列生命周期钩子,主要分为 8 个阶段:
- 创建前/后:
beforeCreate时实例未初始化;created时 data 和 methods 已初始化,但 DOM 尚未挂载。 - 载入前/后:
beforeMount时模板编译完成但未挂载;mounted时实例挂载完成,可操作真实 DOM。 - 更新前/后:
beforeUpdate触发于数据变更但 DOM 未更新时;updated触发于 DOM 更新完成后。 - 销毁前/后:
beforeDestroy时实例仍可用;destroyed时实例解绑事件监听,不可再用。
具体应用场景:
beforeCreate:不能访问 data 或 methods。created:适合发起异步请求、初始化非 DOM 依赖的数据。beforeMount:内存中模板已编译,但页面未渲染。mounted:组件进入运行阶段,适合操作 DOM、插件初始化。beforeUpdate/updated:用于响应数据变化后的 DOM 同步处理。beforeDestroy/destroyed:清理定时器、取消订阅等收尾工作。
3. v-if 和 v-show 的区别?
- 共同点:都能控制元素的显示和隐藏。
- 不同点:
v-show:本质是切换 CSS 的display属性,元素始终存在,只编译一次。适合频繁切换的场景。v-if:动态向 DOM 树添加或删除元素,初始值为 false 时不编译。适合不经常切换的场景,因为切换开销较大。
4. v-if 和 v-for 同时使用在同一个标签上的表现?
当两者共存时,v-for 的优先级高于 v-if。这意味着 v-if 会在每个循环中分别执行。因此不推荐在同一标签上混用,建议将 v-if 移至外层容器,或通过计算属性过滤数据后再渲染。
5. v-for 中的 key 的理解?
key 用于给每个节点做唯一标识,帮助 Diff 算法高效识别节点。正确的 key 能减少不必要的 DOM 重绘和重建,提升虚拟 DOM 更新效率。
6. Vue 中 transition 的理解?
transition 组件用于处理进入、离开和列表过渡动画。主要包含以下 CSS 类:
v-enter/v-enter-active/v-enter-tov-leave/v-leave-active/v-leave-to
可通过 enter-class 等属性自定义类名,或使用 type 指定监听 transitionend 或 animationend。支持设置 duration 和钩子函数(如 before-enter, enter 等)。
7. Vue 的自定义指令?
分为全局指令和局部指令。全局使用 Vue.directive,局部在组件的 directives 选项中定义。
钩子函数:
bind:指令第一次绑定调用。inserted:元素插入父节点时调用。update/componentUpdated:元素更新时调用。unbind:元素移除时调用。
参数说明:
el:绑定的 DOM 元素。binding:对象,包含name,value,oldValue,expression,arg,modifiers。vnode:编译生成的虚拟 DOM。
8. Vue 的实现原理?
Vue 采用数据劫持结合发布者 - 订阅者模式,通过 Object.defineProperty() 劫持属性的 setter 和 getter。
核心步骤:
- Observer:递归遍历数据对象,为所有属性添加 getter/setter,实现数据监听。
- Compile:解析模板指令,替换变量,初始化视图,绑定更新函数。
- Watcher:订阅者桥梁,实例化时将自己添加到订阅器 (dep),数据变动时通知自身 update 方法。
- MVVM:整合 Observer、Compile 和 Watcher,实现数据变化 -> 视图更新,视图交互 -> 数据变更的双向绑定。
9. Vue 的 diff 算法理解?
Diff 算法用于最小化 DOM 操作,避免整棵树重绘。
原理:
- 同层级比较,不跨级。
- 新旧节点对比,调用
patch方法打补丁。 patchVnode判断节点类型,处理文本、子节点差异。updateChildren利用首尾指针优化子节点顺序调整。
10. Vue 组件的通信(父子组件和非父子组件)?
父子通信:
- 父传子:使用
props。 - 子传父:使用
$emit触发自定义事件。
兄弟/跨级通信:
- 事件总线(Event Bus):创建一个空的 Vue 实例作为中间人,通过
$on监听,$emit发送。
// 事件总线实例
import Vue from 'vue'
export default new Vue()
// 发送方
vm.$emit('event-name', data)
// 接收方
vm.$on('event-name', callback)
11. Vue 的路由模式及区别?
- Hash 模式:URL 带
#,不被包含在 HTTP 请求中,兼容性好,无需服务端配置。 - History 模式:基于 HTML5 History API,URL 美观,但需要服务端配置支持,否则刷新可能报 404。
12. Vue 与 React、Angular 的比较?
Vue 特点:
- 轻量级,关注视图层,大小仅几十 KB。
- 中文文档友好,易上手。
- 双向数据绑定,组件化强。
- 虚拟 DOM 性能优异。
React vs Vue:
- React 强制 JSX,脏检查;Vue 提供指令过滤器,更灵活。
- React 社区庞大,生态丰富;Vue 开发体验更平滑。
Angular vs Vue:
- Angular 学习曲线陡峭,依赖注入复杂;Vue API 简单直观。
- Angular 脏检查机制在大量 Watcher 时性能下降;Vue 基于依赖追踪,异步队列更新。
13. Vue Router 的钩子函数?
- 全局钩子:
beforeEach,afterEach。常用于权限校验、登录拦截。 - 路由内钩子:单个路由配置中的
beforeEnter。 - 组件内钩子:
beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave。可直接访问组件实例。
14. Vuex 的使用?
Vuex 是集中式状态管理工具。
- State:单一状态树,存放数据,禁止直接修改。
- Getter:类似计算属性,过滤 State 数据。
- Action:处理异步逻辑,提交 Mutation。
- Mutation:同步修改 State 的唯一方式。
- Modules:模块化拆分,使结构清晰。
15. Vue 的 filter 的理解与用法?
Filter 用于文本格式化,只能在插值表达式 {{ }} 或 v-bind 中使用。
// 全局注册
Vue.filter('uppercase', function (value) {
return value.toUpperCase()
})
// 使用
<h3>{{ message | uppercase }}</h3>
*注:Vue 3 已移除 Filter,推荐使用计算属性或方法替代。
16. Vue 的 keep-alive 的理解?
keep-alive 是内置组件,用于缓存动态组件,保留状态或避免重新渲染。
- 生命周期:激活时触发
activated,退出时触发deactivated。 - 属性:
include(匹配名称缓存)、exclude(排除缓存)。
17. 如何封装一个 Vue 组件?
- 搭建模板结构,编写样式。
- 分析逻辑,定义
props输入。 - 暴露必要的方法或事件作为输出。
- 复用调用。
18. Vue 首屏白屏如何解决?
- 路由懒加载,按需加载组件。
- 开启 Gzip 压缩,CDN 加速。
- 使用 SSR(服务端渲染)。
- 提取公共库(webpack externals)。
- 删除生产环境
console.log。 - 添加 Loading 效果提升感知速度。
19. Vue 中的 v-cloak 的理解?
v-cloak 指令防止编译前的闪烁。配合 CSS [v-cloak] { display: none; } 使用,实例编译完成后自动移除指令。
20. Vue 中 template 编译的理解?
编译过程:Template -> AST(抽象语法树) -> Render Function -> VNode(虚拟 DOM)。
21. v-model 的理解?
v-model 是语法糖,等价于 v-bind:value + v-on:input。用于表单双向绑定。
22. computed 和 watch 的用法和区别?
- Computed:声明式,基于依赖缓存,无副作用,适合数据转换。
- Watch:命令式,数据变化即触发,适合异步操作或开销较大的任务。
23. $nextTick 的使用?
在修改数据后,DOM 更新是异步的。$nextTick 用于在下次 DOM 更新循环结束后执行回调,确保获取最新 DOM。
24. data 为什么是一个函数?
组件复用时,若 data 为对象,所有实例共享同一引用,导致数据污染。函数返回新对象,保证每个实例拥有独立数据空间。
25. Vue 单页面和传统的多页面区别?
- SPA(单页应用):一次加载资源,路由切换不刷新,体验流畅,利于交互,但不利于 SEO。
- MPA(多页应用):每次跳转刷新页面,SEO 友好,首屏加载快,但交互体验稍逊。
26. Vue 常用的修饰符?
.stop:阻止冒泡。.prevent:阻止默认行为。.capture:捕获模式。.self:仅自身触发。.once:只触发一次。
27. Vue 更新数组时触发视图更新的方法?
push(), pop(), shift(), unshift(), splice(), sort(), reverse()。
28. route 和 router 的区别?
- $router:VueRouter 实例,包含路由方法(push, replace, go)。全局对象。
- $route:当前路由信息对象,包含路径、参数、query 等。局部对象。
29. Vue-Router 实现懒加载的方式?
- 异步组件:
resolve => require([...])。 - ES 提案 import():
const Home = () => import('@/components/home')。 - Webpack require.ensure:
r => require.ensure([], () => r(require(...)))。
30. delete 和 Vue.delete 删除数组的区别?
delete:标记为 empty/undefined,键值不变,不触发响应式更新。Vue.delete:物理删除,改变键值,触发响应式更新。
31. 路由跳转和 location.href 的区别?
- location.href:刷新页面,跳转完整 URL。
- 路由跳转:无刷新,SPA 内部导航。
32. Vue 的 slot 的用法?
插槽允许父组件向子组件传递内容。子组件使用 <slot> 占位,父组件在标签内插入内容。支持命名插槽和多插槽。
33. $emit, $on, $once, $off 理解?
- $emit:触发自定义事件。
- $on:监听事件。
- $once:监听一次后自动移除。
- $off:移除监听器。
34. $root, refs, $parent 的使用?
- $root:根实例,可作全局 Store。
- $refs:直接访问 DOM 或组件实例,非响应式。
- $parent:访问父组件实例,慎用以免增加耦合。
35. Vue 开发遇到的问题?
- 样式污染:使用
scoped或唯一 class/id。 - router-link 点击无效:安卓转码问题,需 Babel polyfill。
- 闪屏乱码:使用
v-cloak或display:none配合mounted显示。 - router-link 事件无效:使用
.native修饰符监听原生事件。

