Vue 面试题
背就有分
1. v-if 和 v-show 的区别是什么
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的: 如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
2. $route和 $router的区别是什么
$route
为当前 router 跳转对象,里面可以获取 name, path, query, params, fullPath, matched, hash 等。
$router
为 VueRouter 实例,是一个全局路由对象,包含了路由跳转的方法、钩子函数等,想要导航到不同 URL ,则使用 $router.push()
方法。
3. 请举出 Vue 几种常用的指令
- v-if: 根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。
- v-show: 根据表达式之真假值,切换元素的 display CSS 属性。
- v-for: 循环指令,基于一个数组或者对象渲染一个列表,vue2.0 以上必须配合 key 值使用。
- v-bind: 动态地绑定一个或多个特性,或一个组件 prop 的表达式。
- v-on: 用于监听指定元素的 DOM 事件,比如点击事件。绑定事件侦听器。
- v-model: 实现表单输入和应用状态之间的双向绑定。
- v-pre: 跳过这个元素和它的子元素的编译过程。可以用来显示元素 Mustache 标签。跳过大量没有指令的节点会加快编译。
- v-once: 只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
4. Vue 常用的修饰符有哪些
-
事件修饰符
.stop
阻止单击事件继续传播(阻止冒泡).prevent
阻止事件默认行为.capture
添加事件监听器时使用事件捕获模式,即元素自身触发的事件先在此处理,然后才交由内部元素进行处理.self
只当在 event.target 是当前元素自身时触发处理函数
-
按键修饰符
.enter
.tab
.delete
.esc
.space
.down
.left
.right
-
系统修饰符
-
.ctrl
-
.alt
-
.shift
-
.meta
-
.exact
修饰符允许你控制由精确的系统修饰符组合除法的事件。 -
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 --> <button @click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 没有任何系统修饰符被按下的时候才触发 --> <button @click.exact="onClick">A</button>
-
-
鼠标按钮修饰符
.left
.right
.middle
这些修饰符会限制处理函数仅响应特定的鼠标按钮。
5. v-on 可以绑定多个方法吗
-
v-on 绑定多个方法:
-
<p v-on="{click:dbClick,mousemove:MouseClick}">v-on绑定多个方法</p>
-
-
一个事件绑定多个函数:
-
<p @click="one(),two()">一个事件绑定多个函数</p>
-
6. Vue 中 key 值的作用
key的作用主要是为了高效的更新虚拟DOM。
7. 什么是 Vue 的计算属性
模板内的表达式非常便利,但是设计它们的 初衷是用于简单计算的
。在模板中放入 太多的逻辑会让模板过重且难以维护
。例如:
<div id="example">
{{ message.split('').reverse().join('') }}
</div>
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。
所以,对于任何复杂逻辑,都应当使用计算属性。
例子:
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
结果:
Original message: "Hello"
Computed reversed message: "olleH"
8. 如何定义 vue-router 的动态路由,获取传过来的值
动态路由的创建,主要是使用 path 属性过程中,使用动态路径参数,以冒号开头,如:
{
path: /user/:id
component: User
}
这会是访问 user 目录下的所有文件,如 /user/a 和 /user/b,都会映射到 User 组件
当匹配到 /user 下的任意路由时,参数值会被设置到 this.$route.params 下,所以通过这个属性可以获取到动态参数
9. watch 和 computed 的差异是什么
计算属性computed:
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
- computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
- 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
- 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
侦听属性watch
- 不支持缓存,数据变,直接会触发相应的操作。
- watch支持异步;监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
- 当一个属性发生变化时,需要执行对应的操作;一对多;
- 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数:
immediate: 组件加载立即触发回调函数执行
watch: {
firstName: {
handler(newName, oldName) {
this.fullName = newName + ' ' + this.lastName;
},
// 代表在wacth里声明了firstName这个方法之后立即执行handler方法
immediate: true
}
}
deep: deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler
watch: {
obj: {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
deep: true
}
}
进行优化,给对象的指定属性添加侦听,减少性能开销,这样vue.js会一层一层解析直到遇到属性a,才给a设置监听函数
watch: {
'obj.a': {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
// deep: true
}
}
10. 组件中 data 为什么是函数
当我们的data是一个函数的时候,每一个实例的data属性都是独立的,不会相互影响了。
参考博客 https://www.jianshu.com/p/f3e774c57356
10. 组件中 data 为什么是函数
当我们的data是一个函数的时候,每一个实例的data属性都是独立的,不会相互影响了。
参考博客 https://www.jianshu.com/p/f3e774c57356
11. 请谈谈对于 MVVM 的理解
MVVM
是 Model-View-ViewModel
的缩写,即模型-视图-视图模型。MVVM 是
一种设计思想。
- 模型(
Model
): 数据保存—存放着各种数据,有的是固定写死的,大多数是从后端返回的数据 - 视图 (
View
):用户界面,也就是DOM
- 视图模型(View-Model):连接
View
和Model
的桥梁,当数据变化时,ViewModel
够监听到数据的变化(通过Data Bindings
),自动更新视图,而当用户操作视图,ViewModel
也能监听到视图的变化(通过DOM Listeners
),然后通知数据做改动,这就实现了数据的双向绑定。
MVVM
流程图如下:
12. 第一次页面加载会触发哪几个钩子
会触发 下面这几个 beforeCreate, created, beforeMount, mounted 。
13. DOM 渲染在哪个生命周期中完成
DOM 渲染在 mounted 中就已经完成了。
14. Vue 实现数据双向绑定的原理
1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法;
3.介绍一下Object.defineProperty()方法
(1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法)
(2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;
参考博客 https://www.jianshu.com/p/e7ebb1500613
15. Vue 组件间的参数传递
Vue.js父子组件的关系可以总结为props down,events up,父组件通过props向下传递数据给子组件,子组件通过events给父组件发送消息,它们的工作方式如下图所示:
1).父组件—>子组件:父组件传值给子组件使用Props属性
2).子组件—>父组件:子组件传值给父组件使用Emit事件。
16. Vuex 是什么?怎么使用?哪种功能场景使用它?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
应用场景有:单页应用中,组件之间的数据状态。
应用实例:
1、购物车功能;
2、下单页面有选择优惠券按钮,点击进入优惠券页面,选择后返回到下单页,数据会绑定回来,显示已选择的优惠券;
3、登录状态等等
state
Vuex 使用单一状态树,即每个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不可以直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
类似vue的计算属性,主要用来过滤一些数据。
action
actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
17. 虚拟 DOM 的优缺点
优点:
- 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
- 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
- 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。
缺点:
- 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。
首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。
18. Vue 与 React 的选择
参考博客: https://www.jianshu.com/p/fc3ecea8c3c9
19. Vuex 中 mutation 和 action 的详细区别
参考博客: https://blog.csdn.net/Cool_breeze_/article/details/109659633
20. 简述 Vue 的 diff 算法原理
- 在内存中构建虚拟dom树
- 将内存中虚拟dom树渲染成真实dom结构
- 数据改变的时候,将之前的虚拟dom树结合新的数据生成新的虚拟dom树
- 将此次生成好的虚拟dom树和上一次的虚拟dom树进行一次比对(diff算法进行比对),来更新只需要被替换的DOM,而不是全部重绘。在Diff算法中,只平层的比较前后两棵DOM树的节点,没有进行深度的遍历。、
- 会将对比出来的差异进行重新渲染