Vue2面试核心问题
目录
基础概念
1. Vue的核心特性是什么?
参考答案:
| 特性 |
说明 |
| 响应式数据绑定 |
数据变化自动更新视图 |
| 组件系统 |
组件化开发,可复用 |
| 指令系统 |
v-if/v-for/v-bind/v-on等 |
| 虚拟DOM |
高效的DOMdiff算法 |
| 单文件组件 |
.vue文件包含模板、逻辑、样式 |
2. Vue2和Vue3的区别?
参考答案:
| 对比项 |
Vue2 |
Vue3 |
| 响应式原理 |
Object.defineProperty |
Proxy |
| 组件根节点 |
必须一个根元素 |
支持多根节点(Fragment) |
| API风格 |
Options API |
Composition API + Options API |
| 生命周期 |
beforeCreate/created等 |
onBeforeMount/onMounted等 |
| TypeScript |
partial support |
完整支持 |
| 打包体积 |
~20KB |
~10KB |
| 性能 |
一般 |
优化后更好 |
3. MVVM模式是什么?Vue遵循了吗?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ┌─────────────────────────────────────────────────────────────┐ │ MVVM 模式 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ View │ <--> │ViewModel│ <--> │ Model │ │ │ │ 视图 │ │ 视图模型 │ │ 模型 │ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ │ │ │ │ 模板语法 │ 数据绑定 │ 数据定义 │ │ │ │ │ │ │ └─────────────────┴──────────────────┘ │ │ │ │ Model: data/props/computed │ │ View: template │ │ ViewModel: methods/watch │ └─────────────────────────────────────────────────────────────┘
|
Vue实例作为ViewModel,连接View和Model,实现双向数据绑定。
4. Vue实例有哪些属性?
参考答案:
| 属性 |
说明 |
| $data |
组件实例观察的数据对象 |
| $props |
当前组件接收的props |
| $el |
Vue实例使用的根DOM元素 |
| $options |
当前Vue实例的初始化选项 |
| $parent |
父实例 |
| $root |
当前组件树的根实例 |
| $children |
当前实例的直接子组件 |
| $refs |
DOM元素和组件实例的引用 |
| $slots |
插槽内容 |
| $scopedSlots |
作用域插槽 |
| $attrs |
非props属性 |
组件相关
5. 组件通信方式有哪些?
参考答案:
| 方式 |
适用场景 |
实现方式 |
| props/$emit |
父子通信 |
props向下,$emit向上 |
| $refs |
父访问子 |
this.$refs.child.method() |
| $children |
父访问子 |
this.$children[0].method() |
| $parent |
子访问父 |
this.$parent.method() |
| eventBus |
兄弟/跨级通信 |
emit/on |
| provide/inject |
跨级通信 |
provide/inject |
| Vuex/Pinia |
全局状态 |
store |
6. props有哪些配置项?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| props: { name: String,
value: [String, Number],
required: { type: String, required: true },
age: { type: Number, default: 18 },
items: { type: Array, default() { return [] } },
level: { validator(value) { return [1, 2, 3].includes(value) } } }
|
7. v-model的原理?
参考答案:
1 2 3 4 5
| <input v-model="message">
<input :value="message" @input="message = $event.target.value">
|
对于组件:
1 2 3 4 5
| <custom-input v-model="message">
<custom-input :value="message" @input="message = $event">
|
8. slot的作用域插槽原理?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <!-- Child.vue --> <template> <slot :item="item" :index="index"></slot> </template>
<!-- Parent.vue --> <template> <child> <template #default="{ item, index }"> <div>{{ index }}: {{ item.name }}</div> </template> </child> </template>
|
子组件通过slot将数据传递给父组件,父组件通过解构获取数据。
9. 动态组件是什么?如何实现?
参考答案:
1 2 3 4 5 6 7
| <!-- 使用component + is --> <component :is="currentComponent"></component>
<!-- keep-alive缓存 --> <keep-alive include="Home,About"> <component :is="currentComponent"></component> </keep-alive>
|
响应式原理
10. Vue2响应式原理是什么?
参考答案:
Vue2使用Object.defineProperty实现响应式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function defineReactive(obj, key, val) { const dep = new Dep()
Object.defineProperty(obj, key, { enumerable: true, configurable: true, get() { if (Dep.target) { dep.depend() } return val }, set(newValue) { if (val === newValue) return val = newValue dep.notify() } }) }
|
11. Object.defineProperty的缺点?
参考答案:
| 缺点 |
说明 |
| 无法监听新增属性 |
需要Vue.set |
| 无法监听删除属性 |
需要Vue.delete |
| 无法监听数组索引 |
需要Vue.set或splice |
| 需要递归 |
深层对象需要递归处理 |
| 无法监听Map/Set |
不支持新的数据结构 |
12. $nextTick的原理?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| this.$nextTick(() => { })
function nextTick(cb) { callbacks.push(cb)
if (!pending) { pending = true Promise.resolve().then(flushCallbacks) } }
function flushCallbacks() { callbacks.forEach(cb => cb()) pending = false }
|
13. 数组响应式如何实现?
参考答案:
Vue2对数组方法进行了拦截:
1 2 3 4 5 6 7 8 9 10 11 12 13
| const methods = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ]
methods.forEach(method => { original[method] = function(...args) { const result = original.apply(this, args) dep.notify() return result } })
|
直接通过索引修改数组不会触发更新:
1 2 3 4 5 6 7
| this.items[0] = newValue
this.$set(this.items, 0, newValue)
this.items.splice(0, 1, newValue)
|
14. Watch和Computed的区别?
参考答案:
| 特性 |
Watch |
Computed |
| 用途 |
监听数据变化执行操作 |
依赖数据计算新值 |
| 返回值 |
不必须有 |
必须有返回值 |
| 缓存 |
无 |
有(基于响应式依赖) |
| 执行时机 |
被动触发 |
主动求值 |
| 适用场景 |
异步操作、副操作 |
同步计算 |
路由相关
15. Vue Router有哪几种模式?
参考答案:
1 2 3 4 5
|
location / { try_files $uri $uri/ /index.html; }
|
16. 导航守卫有哪些?
参考答案:
| 守卫 |
说明 |
| beforeEach |
全局前置守卫 |
| beforeResolve |
全局解析守卫 |
| afterEach |
全局后置守卫 |
| beforeEnter |
路由独享守卫 |
| beforeRouteEnter |
组件内守卫 - 进入前 |
| beforeRouteUpdate |
组件内守卫 - 路由变化 |
| beforeRouteLeave |
组件内守卫 - 离开前 |
17. 路由懒加载如何实现?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| { path: '/home', component: () => import('./Home.vue') }
{ path: '/home', component: resolve => require(['./Home.vue'], resolve) }
{ path: '/home', component: () => import( './Home.vue') }
|
状态管理
18. Vuex的核心概念?
参考答案:
| 概念 |
说明 |
| state |
状态定义 |
| getters |
状态计算属性 |
| mutations |
同步修改状态 |
| actions |
异步操作 |
| modules |
模块化管理 |
19. Vuexmutation和action的区别?
参考答案:
| 特性 |
mutation |
action |
| 同步/异步 |
同步 |
异步 |
| 修改state |
直接修改 |
通过mutation修改 |
| 事务调试 |
可追踪 |
异步难以追踪 |
| 参数 |
state + payload |
context + payload |
20. Vuex数据流程?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| ┌─────────────────────────────────────────────────────────────┐ │ Vuex 数据流程 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ Component │ │ │ │ │ │ dispatch('action') │ │ ▼ │ │ Action ───────────────────────────────────────────────┐ │ │ │ │ │ │ │ async operation │ │ │ ▼ │ │ │ Mutation ◄──────────────────────────────────────────────┘ │ │ │ │ │ │ commit('mutation') │ │ ▼ │ │ State │ │ │ │ │ │ reactive │ │ ▼ │ │ Component │ │ │ └─────────────────────────────────────────────────────────────┘
|
性能优化
21. Vue性能优化方法?
参考答案:
| 优化点 |
方法 |
| 代码分割 |
路由懒加载、组件懒加载 |
| 减少重排重绘 |
使用transform/opacity |
| 列表key |
使用唯一id而非index |
| 合理使用响应式 |
不需要响应式的用Object.freeze |
| keep-alive |
缓存不活跃组件 |
| v-show vs v-if |
频繁切换用v-show |
| 事件销毁 |
及时清理定时器/监听 |
| 函数式组件 |
无状态用functional |
22. 为什么列表需要key?
参考答案:
- 快速定位: key帮助Vue追踪每个节点,实现就地复用
- 保持状态: 列表顺序变化时,key确保组件状态正确
- 提高性能: 减少DOM操作,提高渲染性能
1 2 3 4 5
| <li v-for="(item, index) in items" :key="index">
<li v-for="item in items" :key="item.id">
|
23. v-if和v-show的区别?
参考答案:
| 特性 |
v-if |
v-show |
| 原理 |
动态添加/删除DOM |
切换display |
| 初始渲染 |
条件为false不渲染 |
条件为false渲染但隐藏 |
| 切换开销 |
高(DOM操作) |
低(CSS切换) |
| 适用场景 |
运行时很少改变 |
频繁切换 |
24. keep-alive的原理?
参考答案:
- 缓存机制: 使用ache对象存储已缓存的组件实例
- 生命周期: 提供activated/deactivated钩子
- 最大缓存: 通过max属性限制缓存数量
1 2 3
| <keep-alive :max="10" :include="['Home', 'About']"> <component :is="currentComponent"></component> </keep-alive>
|
实际应用
25. 如何实现一个权限控制按钮?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Vue.directive('permission', { inserted(el, binding) { const { value } = binding const userPermissions = store.state.user.permissions || []
if (!userPermissions.includes(value)) { el.parentNode.removeChild(el) } } })
<button v-permission="'user:delete'">删除</button>
|
26. 如何实现一个表单验证?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const rules = { name: [ { required: true, message: '请输入名称', trigger: 'blur' }, { min: 2, max: 10, message: '名称长度2-10', trigger: 'blur' } ], email: [ { type: 'email', message: '邮箱格式错误', trigger: 'blur' } ] }
<el-form :model="form" :rules="rules"> <el-form-item prop="name"> <el-input v-model="form.name"></el-input> </el-form-item> </el-form>
|
27. 如何封装一个请求?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| import axios from 'axios' import { Message } from 'element-ui'
const service = axios.create({ baseURL: process.env.VUE_APP_API, timeout: 10000 })
service.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config })
service.interceptors.response.use( response => { const { code, data, message } = response.data if (code !== 0) { Message.error(message) return Promise.reject(response.data) } return data }, error => { if (error.response.status === 401) { } return Promise.reject(error) } )
export default service
|
28. 如何排查Vue应用性能问题?
参考答案:
- Vue DevTools: 使用Timeline查看组件渲染性能
- Chrome DevTools: Performance面板分析
- Vue Performance: vue-addons性能检测
- Vue.config.performance: 开启性能追踪
总结
Vue2核心知识图谱
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| ┌─────────────────────────────────────────────────────────────┐ │ Vue2 核心知识图谱 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 基础 │ │ ├── 模板语法 (插值/指令/事件) │ │ ├── 计算属性和侦听器 │ │ └── 过滤器 │ │ │ │ 组件 │ │ ├── 组件通信 (props/$emit/$refs/eventBus) │ │ ├── 插槽 (默认/具名/作用域) │ │ ├── 动态组件 (component + keep-alive) │ │ └── 生命周期 │ │ │ │ 原理 │ │ ├── 响应式原理 (Object.defineProperty) │ │ ├── 虚拟DOM (Snabbdom/VDOM diff) │ │ └── 异步更新 ($nextTick) │ │ │ │ 生态 │ │ ├── Vue Router (导航守卫/懒加载) │ │ └── Vuex (state/getters/mutations/actions) │ │ │ └─────────────────────────────────────────────────────────────┘
|
相关链接