Vue面试题

本文将面试题作为学习使用,便于查缺补漏,将持续更新……

vue原理

Vue中什么是双向绑定?原理是什么?

答案来源

双向绑定指视图(View) 和 数据模型(Model)之间的双向绑定

其原理是采用数据劫持结合发布者 - 订阅者模式的方式来实现。

Vue先遍历data选项中所有的属性(发布者)用object.defineProperty劫持这些属性将其转为getter/setter。读取数据的时候会触发getter。修改数据的时候会触发setter。

然后给每个属性对应new Dep(), Dep()专门用来收集依赖关系、删除依赖、向依赖发消息的。先让每个依赖设置在Dep.target上,在Dep中创建一个依赖数组,先判断Dep.target是否在依赖中已经存在,不存在的话添加到依赖数组中完成依赖收集,随后将Dep.target置位上一个依赖。

组件在挂载过程中都会new一个Watcher实例(这个实例就是依赖,即订阅者)。Watcher第二个参数是一个函数,这个函数的作用时更新和渲染节点。在首次渲染时,会自动调用Dep方法来收集依赖,收集完成之后,组件中的每个数据都绑上该依赖。当数据变化时,就会在setter中通知对应的依赖来进行更新。在更新过程中要先读取数据,就会触发Watcher的第二个函数参数。一触发就会再次自动调用Dep方法收集依赖,同时在此函数中运行patch(diff运算)来更新对应的Dom节点,完成双向绑定。

谈一下你对 Vue.js 的 MVVM 原理的理解

MVVM的前身是MVC,即Model-View-Controller, 使用MVC的目的就是将Model和View的代码分离。‘MVC是单向通信的。

MVVM即Model-View-ViewModel,顾名思义即是模型-视图-视图模型之间的相互关系。Model 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑,简单来说可以把Model 理解成支持前端页面展示的数据。View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,也就是平时看到的页面。ViewModel 监听模型数据的改变和控制视图⾏为、处理⽤户交互,简单理解就是⼀个同步View 和 Model 的对象,连接 Model 和 View,将后端的数据传递给前端展示,将前端看到的页面转换成后端的数据。

总结:在MVVM的框架下Model和View是不能直接通信的。它们通过ViewModel来通信,ViewModel是框架的核心,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。

MVC和MVVM的区别并不是ViewModel完全取代了Controller,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。

Vue原理双向绑定可点击查看

该题参考链接:
链接1
链接2

深入理解

Vue.js 中是如何检测数组变化?

答案:

  • 使用函数劫持的方式,重写了数组的方法
  • Vue将data中的数组,进行了原型链重写。指向了自己定义的数组原型方法,这样当调用数组api时,可以通知依赖更新.如果数组中包含着引用类型。会对数组中的引用类型再次进行监控。

可以看vue源码便于理解:
在这里插入图片描述

那为什么说vue无法监听数组的变化呢,这又是怎么回事:

注意事项
由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
当你利用索引直接设置一个项时,例如: vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如: vm.items.length = newLength
为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果, 同时也将触发状态更新:
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)
为了解决第二类问题,你可以使用 splice:
example1.items.splice(newLength)

该问题解决方案

文章参考链接:
链接1
链接2

### Vue 面试题及答案 #### 1. Vue.js 的响应式原理是什么? Vue.js 利用 **Object.defineProperty**(Vue 2.x)或 **Proxy**(Vue 3.x)来劫持数据对象的读写操作。当数据发生变化时,Vue 能够检测到这些变化,并通知相关的视图进行更新。这种机制使得数据和视图保持同步,而无需手动操作 DOM。 具体来说,Vue 会递归地将数据对象的所有属性转换为 getter 和 setter,从而实现对数据的监听。在 Vue 3.x 中,使用 Proxy 替代了 Object.defineProperty,提供了更强大的功能和更好的性能[^1]。 #### 2. Vue 组件之间的通信方式有哪些? - **props / $emit**:父组件通过 props 向子组件传递数据,子组件通过 $emit 向父组件发送事件。 - **v-model**:本质上是 props 和 $emit 的语法糖,用于双向绑定数据。 - **provide / inject**:祖先组件向后代组件提供数据,不需要逐级传递。 - **Event Bus**:通过一个全局的 Vue 实例作为事件总线,实现任意组件间的通信。 - **Vuex**:适用于复杂应用的状态管理工具,集中管理应用的状态。 #### 3. Vue 生命周期钩子函数有哪些?分别在什么时候触发? Vue 组件的生命周期可以分为以下几个阶段: - **beforeCreate**:实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。 - **created**:实例已经创建完成,属性已绑定,但 DOM 还未生成。 - **beforeMount**:挂载开始之前被调用。 - **mounted**:DOM 已经渲染完毕,可以访问真实的 DOM 元素。 - **beforeUpdate**:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 - **updated**:数据更新后调用,虚拟 DOM 重新渲染并应用补丁。 - **beforeUnmount**:实例销毁之前调用。 - **unmounted**:实例销毁后调用。 #### 4. Vue 3 相比 Vue 2 有哪些改进? - **更快的运行速度**:Vue 3 使用 Proxy 来实现响应式系统,相比 Vue 2 的 Object.defineProperty 更加高效。 - **更小的体积**:Vue 3 通过模块化设计和 Tree-shaking 技术,显著减少了框架的体积。 - **更好的 TypeScript 支持**:Vue 3 原生支持 TypeScript,提供了更好的类型推导和开发体验。 - **Composition API**:引入了类似于 React Hook 的 Composition API,使代码组织更加灵活和可复用。 - **更好的可维护性和扩展性**:Vue 3 的架构更加模块化,便于长期维护和扩展。 #### 5. Vue 中的 computed 和 watch 有什么区别? - **computed**:计算属性基于它们的依赖进行缓存,只有在其依赖的数据发生变化时才会重新计算。适合处理复杂的逻辑和模板中的表达式。 - **watch**:观察某个数据的变化,并执行相应的回调函数。适用于异步操作或需要执行开销较大的任务。 #### 6. Vue 中的 key 属性有什么作用? `key` 属性主要用于标识列表中每个元素的唯一性。当 Vue 渲染列表时,它会尽可能高效地复用现有的元素,而不是重新创建新的元素。通过设置唯一的 `key`,可以帮助 Vue 更准确地判断哪些元素发生了变化,从而提高渲染效率。 #### 7. Vue 中的 v-if 和 v-show 有什么区别? - **v-if**:根据条件决定是否渲染元素。如果条件为假,则元素不会出现在 DOM 中。 - **v-show**:通过 CSS 的 `display` 属性控制元素的显示与隐藏。无论条件如何,元素始终存在于 DOM 中。 #### 8. Vue 中的 nextTick 是什么?有什么用途? `nextTick` 是 Vue 提供的一个方法,用于在下次 DOM 更新循环结束后执行回调函数。由于 Vue 的响应式系统是异步更新的,因此在某些情况下,直接访问或操作 DOM 可能无法获取最新的状态。通过 `nextTick`,可以确保在 DOM 更新完成后执行相关操作。 #### 9. Vue 中的 mixin 是什么?有什么优缺点? - **mixin**:是一种分发 Vue 组件中可复用功能的方式。可以通过定义 mixin 对象,包含组件的选项(如 data、methods、生命周期钩子等),然后将其混入到多个组件中。 - **优点**:提高代码的复用性和可维护性。 - **缺点**:可能导致命名冲突和逻辑混乱,特别是在大型项目中使用过多的 mixin 时。 #### 10. Vue 中的插槽(slot)是什么?如何使用? 插槽是 Vue 提供的一种内容分发机制,允许父组件向子组件传递 HTML 内容。通过 `<slot>` 标签,可以在子组件中预留一个位置,供父组件填充内容。 - **默认插槽**:父组件直接传递内容给子组件。 - **具名插槽**:通过 `name` 属性指定不同的插槽位置。 - **作用域插槽**:子组件可以向父组件传递数据,父组件可以根据这些数据自定义内容。 ```html <!-- 子组件 --> <template> <div> <slot name="header"></slot> <p>主要内容</p> <slot name="footer"></slot> </div> </template> <!-- 父组件 --> <template> <child-component> <template #header> <h1>头部内容</h1> </template> <template #footer> <p>底部内容</p> </template> </child-component> </template> ``` #### 11. Vue 中的 keep-alive 是什么?有什么用途? `keep-alive` 是 Vue 提供的一个内置组件,用于缓存动态组件的状态。当组件被切换时,`keep-alive` 可以保留组件的状态,避免重复渲染和初始化。这对于提升用户体验和性能非常有帮助。 ```html <keep-alive> <component :is="currentComponent"></component> </keep-alive> ``` #### 12. Vue 中的 directive 是什么?如何自定义指令? 指令是 Vue 提供的一种特殊的属性,用于直接操作 DOM。常见的内置指令包括 `v-model`、`v-show`、`v-if` 等。 要自定义指令,可以通过 `directives` 选项定义一个对象,包含 `bind`、`inserted`、`update`、`componentUpdated` 和 `unbind` 等钩子函数。 ```javascript // 自定义指令 directives: { focus: { inserted(el) { el.focus(); } } } ``` #### 13. Vue 中的 Vuex 是什么?有什么作用? Vuex 是 Vue 官方提供的状态管理模式和库,用于管理应用中的共享状态。它采用集中式存储管理所有组件的状态,并提供了一套规则来保证状态的变化是可以预测的。 - **State**:存储应用的状态。 - **Getters**:从 state 中派生出一些状态。 - **Mutations**:修改 state 的唯一方式,必须是同步函数。 - **Actions**:提交 mutations,可以包含异步操作。 - **Modules**:将 store 分割成模块,每个模块拥有自己的 state、getters、mutations、actions。 #### 14. Vue 中的 router 是什么?如何实现路由导航? Vue Router 是 Vue 官方的路由管理器,用于构建单页应用(SPA)。它提供了声明式的路由配置、嵌套路由、动态路由等功能。 要实现路由导航,可以通过 `<router-link>` 组件或编程式导航(`$router.push`、`$router.replace` 等)。 ```html <router-link to="/home">首页</router-link> ``` ```javascript this.$router.push('/about'); ``` #### 15. Vue 中的 Composition API 是什么?有什么优势? Composition API 是 Vue 3 引入的新特性,类似于 React Hook,允许开发者在不使用类组件的情况下,更好地组织和复用逻辑代码。它提供了一系列函数(如 `ref`、`reactive`、`watch`、`computed` 等),帮助开发者更灵活地管理组件的状态和逻辑。 - **优势**: - 提高代码的可读性和可维护性。 - 更好的类型推导和支持 TypeScript。 - 更容易复用逻辑代码。 ```javascript import { ref, onMounted } from 'vue'; export default { setup() { const count = ref(0); function increment() { count.value++; } onMounted(() => { console.log('组件已挂载'); }); return { count, increment }; } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值