Vue.js 面试题集合
Vue.js 面试题集合
📋 目录
- 基础概念 (1-3题)
- 响应式原理 (4-5题)
- 组件通信 (6-14题)
- 生命周期 (15-17题)
- 指令系统 (18-19题)
- 计算属性和侦听器 (20-22题)
- 路由 (23-24题)
- 状态管理 (25-27题)
- 性能优化 (28-30题)
- 虚拟DOM和diff算法 (31-33题)
- 高级特性 (34-38题)
- 实际应用 (39-41题)
- 编程题 (42-43题)
基础概念
1. 什么是Vue.js?
Vue.js是一个渐进式JavaScript框架,用于构建用户界面。它采用自底向上增量开发的设计,核心库只关注视图层,易于上手,便于与第三方库或既有项目整合。
2. Vue的核心特性有哪些?
- 响应式数据绑定:数据变化时自动更新视图
- 组件化:可复用的组件系统
- 指令系统:v-if、v-for、v-model等
- 虚拟DOM:提高渲染性能
- 单文件组件:.vue文件格式
3. Vue 2 和 Vue 3 的主要区别?
- Composition API:Vue 3引入了新的组合式API
- 性能提升:更小的包体积,更快的渲染
- TypeScript支持:更好的TypeScript集成
- 多根节点:template可以有多个根节点
- Teleport:可以将组件渲染到DOM的任意位置
响应式原理
4. Vue的响应式原理是什么?
Vue 2 响应式原理:
- 数据劫持:使用Object.defineProperty()劫持data中所有属性的getter/setter
- 依赖收集:在getter中收集依赖(Watcher),当组件渲染时触发
- 派发更新:在setter中通知所有依赖更新
- 异步更新:使用nextTick进行异步批量更新
Vue 3 响应式原理:
- Proxy代理:使用Proxy代理整个对象,监听所有操作
- track追踪:在getter中追踪依赖
- trigger触发:在setter中触发更新
- effect副作用:使用effect函数管理副作用
核心实现对比:
// Vue 2 核心实现
Object.defineProperty(obj, key, {get() {// 依赖收集if (Dep.target) {dep.depend()}return val},set(newVal) {if (newVal === val) returnval = newVal// 通知更新dep.notify()}
})// Vue 3 核心实现
const proxy = new Proxy(target, {get(target, key, receiver) {track(target, key) // 依赖收集return Reflect.get(target, key, receiver)},set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver)trigger(target, key) // 触发更新return result}
})
核心流程:
// 1. 初始化响应式数据
const data = reactive({count: 0,name: 'Vue'
})// 2. 组件渲染时收集依赖
function render() {return h('div', data.count) // 访问data.count,触发getter,收集依赖
}// 3. 数据变化时触发更新
data.count++ // 触发setter,通知依赖更新,重新渲染
5. 什么是依赖收集?
依赖收集是响应式系统的核心机制:
- 收集时机:当组件渲染时,会触发数据的getter
- 收集对象:将当前组件的Watcher作为该数据的依赖
- 通知更新:当数据发生变化时,会通知所有依赖进行更新
- 避免无效更新:只有真正使用了数据的组件才会被收集为依赖
6. 描述Vue组件渲染和更新的过程?
初始渲染过程:
- 解析模板:将template编译成render函数
- 创建响应式数据:通过Observer对data进行响应式处理
- 执行render函数:生成虚拟DOM树
- 创建真实DOM:将虚拟DOM转换为真实DOM并挂载
更新过程:
- 数据变化:响应式数据发生改变
- 触发依赖:通知相关的Watcher进行更新
- 重新执行render:生成新的虚拟DOM树
- diff算法:对比新旧虚拟DOM,找出差异
- patch更新:只更新发生变化的DOM节点
7. 对MVVM的理解?
MVVM是Model-View-ViewModel的缩写:
- Model:数据模型,对应Vue中的data
- View:视图层,对应Vue中的template
- ViewModel:视图模型,对应Vue实例,连接Model和View
Vue中的MVVM体现:
- Vue实例作为ViewModel,通过数据绑定连接Model和View
- 当Model发生变化时,ViewModel会自动更新View
- 当View发生变化时(如表单输入),ViewModel会自动更新Model
- 实现了数据的双向绑定,开发者只需关注数据逻辑
8. 双向数据绑定v-model的实现原理?
v-model本质上是语法糖,它结合了属性绑定和事件监听:
// v-model="message" 等价于:
<input :value="message" @input="message = $event.target.value">
实现原理:
- 属性绑定:将数据绑定到表单元素的value属性
- 事件监听:监听input事件,当用户输入时更新数据
- 不同元素的处理:
- input/textarea:监听input事件,绑定value属性
- checkbox:监听change事件,绑定checked属性
- radio:监听change事件,绑定checked属性
- select:监听change事件,绑定value属性
组件通信
9. Vue组件间通信的方式有哪些?
- props / $emit:父子组件通信
- $parent / $children:直接访问父子组件实例
- provide / inject:祖先组件向后代组件传递数据
- EventBus:事件总线,用于兄弟组件通信
- Vuex:状态管理,适用于复杂应用
- $attrs / $listeners:透传属性和事件
10. 如何实现父子组件双向数据绑定?
// 父组件
<child-component v-model="parentValue" />// 子组件
props: ['value'],
methods: {updateValue(newValue) {this.$emit('input', newValue)}
}
11. Ajax请求应该放在哪个生命周期?
推荐在created或mounted中发起Ajax请求:
- created:实例创建完成,可以访问data和methods,适合不需要DOM的数据请求
- mounted:DOM挂载完成,适合需要操作DOM的场景
具体选择:
// 推荐:在created中请求数据
created() {this.fetchData()
},// 或者在mounted中
mounted() {this.fetchUserInfo()
}
不建议在beforeCreate中:此时data和methods还未初始化
服务端渲染(SSR)注意:mounted在服务端不会执行,应该使用created
12. 如何自己实现v-model?
方法一:在组件中实现
// 子组件
<template><input :value="currentValue" @input="handleInput" />
</template><script>
export default {props: {value: {type: String,default: ''}},data() {return {currentValue: this.value}},watch: {value(newVal) {this.currentValue = newVal}},methods: {handleInput(event)