# Vue 面试题
# 一、v-if 和 v-for 的区别
# 1. 两者的作用
v-if 指令:用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 值的时候被渲染。
v-for 指令:基于一个数组来渲染一个列表。v-for 建议设置 key 值,并且保证每个 key 值是独一无二的,这便于 diff 算法进行优化。需要使用 item in items 形式的特殊语法(item 是被迭代的数组元素的别名,items 是源数据数组或者对象)。
两者在用法上区别如下:
<div v-if="isShow" >123</div>
<li v-for="item in items" :key="item.id">
{{ item.label }}
</li>
# 2. 两者的优先级
- 2.x 版本中在一个元素上同时使用 v-if 和 v-for 时,v-for 的优先级高。
- 3.x 版本中 v-if 总是优先于 v-for 生效。
# 3. 注意事项
首先在官方文档中明确指出 v-for 和 v-if 不建议一起使用。
永远不要把 v-if 和 v-for 同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断),如果避免出现这种情况,则在外层嵌套 template(页面渲染不生成 dom 节点),在这一层进行 v-if 判断,然后在内部进行 v-for 循环。
<template v-if="isShow">
<p v-for="item in items">
</template>
如果条件出现在循环内部,可通过计算属性 computed 提前过滤掉不需要显示的项。
computed: {
items: function() {
return this.list.filter(function (item) {
return item.isShow
})
}
}
# 二、v-if 与 v-show 的区别
共同点: 都是动态显示 DOM 元素。
区别:
| v-if | v-show | |
|---|---|---|
| 手段 | 通过控制 DOM 节点的存在与否来控制元素的显隐 | 通过设置 DOM 元素的 display 样式,(block 为显示,none 为隐藏) |
| 编译条件 | 是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译 | 是在任何条件下(首次条件是否为真)都被编译,然后被缓存,而且 DOM 元素保留 |
| 编译过程 | 切换有一个局部编译 / 卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件 | 只是简单的基于 css 切换 |
| 性能消耗 | 有更高的切换消耗 | 有更高的初始渲染消耗 |
| 使用场景 | 适合运行条件很少改变 | 适合频繁切换 |
# 三、Vue / React 项目中的 key
- 作用:
- 为了在 diff 算法执行时更快的找到对应的节点,提高 diff 速度,更高效的更新虚拟 DOM。
- 为了在数据变化时强制更新组件,以避免“就地复用”带来的副作用。
- 开发中如何选择 key?
最好使用每条数据的唯一标识符作为 key,比如 id、手机号、身份证号、学号等唯一值。
# 四、组件中的 data 函数
data 为什么是一个函数?
如果 data 是对象的话,对象属于引用类型,会影响到所有的实例。new Vue 的实例,是不会被复用的,所以为了保证组件不同的实例之间 data 不冲突,data 必须是一个函数。
# 五、Vue 组件的通信方式
父子组件 props / $emit、$on:
- 父 ──> 子:用 props,可以极大的提高组件的复用性。
- 子 ──> 父:用 $on、$emit,获取父子组件实例 parent、children Ref 获取实例的方式调用组件的属性或者方法。
- 父 ──> 子孙:用 Provide、inject 官方不推荐使用,但是写组件库时很常用。
兄弟组件 $emit / $on:
Event Bus 实现跨组件通信 Vue.prototype.$bus = new Vue() 自定义事件。跨级组件 Vuex: Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。
# 六、Vue 的生命周期
每个 Vue 实例在创建时都会经过一系列的初始化过程,vue 的生命周期钩子,就是说在达到某一阶段或条件时去触发的函数,目的就是为了完成一些动作或者事件。
create 阶段:vue 实例被创建。
- beforeCreate: 创建前,vue 实例的挂载元素 el 和数据对象 data 都为 undefined,还未初始化。
- created: 创建后,vue 实例的数据对象 data 中有值,el 还没有。
mount 阶段: vue 实例被挂载到真实 DOM 节点。
- beforeMount:vue 实例的 el 和 data 都初始化了,挂载之前为虚拟 DOM 节点,data 尚未替换。
- mounted: vue 实例挂载完成,data 成功渲染,此时可以操作 DOM。
update 阶段:当 vue 实例里面的 data 数据变化时,触发组件的重新渲染。
- beforeUpdate:更新前 。
- updated:更新后。
destroy 阶段:vue 实例被销毁。
- beforeDestroy:实例被销毁前,此时可以手动销毁绑定的事件(通过 removeEventListener)。
- destroyed:销毁后。vue 实例已经解除了事件监听以及 dom 的绑定,但是 dom 结构依然存在。