首先我们先看几个面试题
先看几个面试题,自己去思考一下,自己能回答上多少,在去对比一下面试题的答案
思考如何应对这些面试题、以及所以的面试
一、Vue 面试题
1、v-sho 和 v-if 的区别是什么
区别:
(1)、当条件为真的时候 没有区别 当条件为假的时候 v-if是不创建元素 v-show 渲染元素然后隐藏掉
(2)、v-if更适合数据的筛选和初始渲染, v-show更适合元素的切换
2、为何 v-for 中要用 key
(1)、vue中列表循环需加:key=“唯一标识” 唯一标识尽量是item里面id等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM。
(2)、key主要用来做dom diff算法用的,diff算法是同级比较,比较当前标签上的key还有它当前的标签名,如果key和标签名都一样时只是做了一个移动的操作,不会重新创建元素和删除元素。
(3、)没有key的时候默认使用的是“就地复用”策略。如果数据项的顺序被改变,Vue不是移动Dom元素来匹配数据项的改变,而是简单复用原来位置的每个元素。如果删除第一个元素,在进行比较时发现标签一样值不一样时,就会复用之前的位置,将新值直接放到该位置,以此类推,最后多出一个就会把最后一个删除掉。
(4)、尽量不要使用索引值index作key值,一定要用唯一标识的值,如id等。因为若用数组索引index为key,当向数组中指定位置插入一个新元素后,因为这时候会重新更新index索引,对应着后面的虚拟DOM的key值全部更新了,这个时候还是会做不必要的更新,就像没有加key一样,因此index虽然能够解决key不冲突的问题,但是并不能解决复用的情况。如果是静态数据,用索引号index做key值是没有问题的。
(5)、标签名一样,key一样这时候就会就地复用,如果标签名不一样,key一样不会复用。
3、描述 Vue 组件生命周期(有父子组件的情况)
加载渲染过程
父beforeCreate —> 父created —> 父beforeMount —> 子beforeCreate —> 子created —> 子beforeMount —> 子mounted —> 父mounted
子组件更新过程
父beforeUpdate —> 子beforeUpdate —> 子updated —> 父updated
父组件更新过程
父beforeUpdate —> 父updated
销毁过程
父beforeDestroy —> 子beforeDestroy —> 子destroyed —> 父destroyed
4、Vue 组件如何通讯
Vue组件间的通信,大致分为以下几种:
- 使用props属性。
props主要用于父组件传递数据给子组件,是你可以在组件上注册一些自定义特性。当一个值传递给一个prop特性的时候,它就变成了那个组件实例的一个属性。这样在子组件就可以使用该该值。请注意:所有的prop都使得期父子prop之间形成了一个单向下行绑定,即父级prop的更新会向下流动到子组件,但是反过来就不行,子组件不能改变父组件的状态。
每次父组件发生更新时,子组件中所有的prop都会被刷新为最新的值。
在实例中演示如下:
在父组件中引用 TodoList组件,使用 :todos (v-bind:todos)传递一个数组,使用 :deleteTodo 传递一个函数,
子组件中使用props接收传入的参数,然后在本组件使用。无需再data中定义。 当传递函数给子组件,也就意味着, 子组件需要修改父组件的某一项值,但是无法自己修改,只能将 特定值(例如数组的某个角标 )传递或者不传参给父组件,通知父组件进行更新操作(例如删除 数组中的一个元素)。
- 使用Vue自定义事件。
怎么使用呢?
- 父组件可以在使用子组件的地方直接用 v-on来监听子组件触发的事件 。即父组件中使用 v-on绑定自定义事件,然后在子组件中使用 $emit(eventName,data)触发事件。使用如下所示:
addTodo是一个函数,函数的具体内容不再展示了, 在子组件通过$emit 来触发该事件。
请注意: 该方式,仅仅用于父子组件传递,不适用于 三层及其以上
-
每个Vue对象实例都实现了事件接口,所以可以使用 on(eventName)监听事件,使用on(eventName)监听事件,使用on(eventName)监听事件,使用emit 来触发事件.
父组件挂载的时候,为该子组件绑定监听事件:
子组件中还是通过 $emit 来触发事件。 -
消息订阅与发布(PubSubJS库)
订阅消息 PubSub.subscribe(‘msg’,function(msg,data){} )
发布消息 : PubSub.publish(‘msg’,data)
注意:先要导入 PubSub组件 import PubSub from ‘pubsub-js’
// 订阅消息
//PubSub.subscribe('deleteTodo',function(msg,data){
// this.deleteTodo(index) ;
// 这样是存在问题的,是因为this使用的是回调函数中的,并不是外部的this ,于是,可以使用箭头函数,将外部this绑定
//})
PubSub.subscribe('deleteTodo', (msg,data) =>{// 箭头函数,绑定的是外部的this
this.deleteTodo(index);
})
在另一组件中发布消息:
// 注意先导入 PubSub
PubSub.publish('deleteTodo',index) // indx 为传入的数据
注意: 1)优点:此方式可实现任意关系组件间通信(数据)
- 组件间通信:Slot
此方式用于父组件向子组件传递"标签数据"。也即子组件先有一个"占位符", 等待父组件传入具体的标签,子组件在进行渲染。
用法:
子组件:
// 子组件 :Child.vue
<template>
<div>
<slot name="xxx"> 不确定的标签结构1</slot> <!--定义架子,我理解为定义一个占位符 -->
<div> 组件确定的标签结构</div>
<slot name="yyy">不确定的标签结构2</slot>
</div>
</template>
父组件:
// 父组件:Parent.vue
<child>
<div slot="xxx">xxx对应的标签结构</div> <!-- 实际的标签结构-->
<div slot="yyy">yyy对应的标签结构</div> <!-- 实际的标签结构-->
</child>
注意: 因为传递的具体的标签是在父组件,所以操作也应该放在父组件中。也就是说应该在父组件运行好之后传入子组件,其所有的操作应该在父组件中进行。
如下所示,对子组件的这些操作,全部放入到父组件中:
5、描述组件渲染和更新的过程
1、vue 组件初次渲染过程
解析模板为 render 函数
触发响应式,监听 data 属性的 getter 和 setter
执行 render 函数, 生成 vnode,patch(elem,vnode)
2、vue 组件更新过程
修改 data, 触发 setter (此前在getter中已被监听)
重新执行 render 函数,生成 newVnode
patch(vnode, newVnode)
5、双向数据绑定 v-model 的实现原理
vue中的v-model可以实现双向绑定,其核心思想通过Object.definePropery来对Vue的数据进行数据劫持,
主要分为三部分
observer主要是负责对Vue数据进行数据劫持,使其数据拥有get和set方法
指令解析器负责绑定数据和指令,绑定试图更新方法
watcher负责数据监听,当数据发生改变通知订阅者,调用视图更新函数更新视图