1. v-if和v-show的区别
- v-if直接在dom结构上创建和销毁
- v-show通过设置样式display来显示和隐藏,一直存在dom结构中
- 对于频繁切换建议使用v-show,不频繁切换操作的使用v-if
2. 为何v-for中要用key
虚拟dom的比对根据key做关联,如果key一样可以实现复用,提高性能
3. 不建议使用index做key
因为index存在不稳定性,不容易实现复用
4. 描述Vue组件生命周期(有父子组件的情况)
- Vue2中的生命周期:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
- Vue3中的生命周期
- onBeforeCreate()
- onCreated()
- onBeforeMount()
- onMounted()
- onBeforeUpdate()
- onUpdated()
- onBeforeUnmount()
- onUnmounted()
- 挂载阶段: beforeMount父 -> beforeMount子 -> mounted子 -> mounted父
- 更新阶段 beforeUpdate父 -> beforeUpdate子 -> updated子 -> updated父
- 销毁阶段 beforeDestroy父 -> beforeDestroy子 -> destroyed子 -> destroyed父
5. Vue组件如何通讯
-
父子组件通讯
- 父组件通过props向子组件传递参数
- 子组件通过$emit向父组件触发事件
-
自定义事件(总线机制)
- 使用vue实例自带的emit、$off进行通讯
import Vue from 'vue'; export default new Vue(); import event from './event.js'; event.$emit('getInfo', "你好"); event.$on('getInfo', this.addGetInfo); event.$off('getInfo', this.addGetInfo); 注意:在beforeDestroy(){}生命周期及时销毁自定义事件,避免内存泄漏 event.$off() -
Vuex
6. 自定义v-model
7. mixin的作用及问题
- 作用:提取组件间的公共逻辑
- 问题:
- 多变量来源不明确,不利于阅读
- 多个mixin可能回造成变量冲突
- mixin和组件可能存在多对多关系,复杂度较高
- 使用
// mixin.js
export default {
data(){
return {
name: "你好我是mixin"
}
},
methods: {
change(){
this.name = "我已经修改了呦"
}
}
}
// test.vue
<template>
<div>
<h2>
mixin用法
</h2>
<p>
{{name}}
</p>
<button @click="change">改变内容</button>
</div>
</template>
<script>
import myMixin from './mixin';
export default {
mixins: [myMixin], // 可以添加多个用逗号隔开,会自动合并
}
</script>
8. 动态组件和异步组件
9. 什么是MVVM
- MVVM 是 Model-View-ViewModel的缩写
- Model 表示数据层,用于存放数据
- View 表示视图层,页面展示数据
- ViewModel 用于同步 View 和 Model 之间的关联。核心是 Dom Listeners 和 Data Bindings 两个工具。Dom Listeners 用于监听 View 中 DOM 的变化,并会选择性的传递给 Model;Data Bindings 用于监听 Model数据的变化,并更新给 View。
10. 为什么Vue组件中data必须是个函数
- 如果data是个对象,组件进行复用的时候,都会指向同一地址,造成变量污染
- 如果data通过函数返回对象,每个对象都是一个新的对象,就不会有这一问题
11. Vue中computed和watch有什么区别
- computed计算属性
- 支持缓存,只有依赖的数据发生变化时才会重新计算
- 计算属性内不支持异步操作
- 计算属性的函数都一个get和set方法,使用计算属性进行双向数据绑定一定要使用get和set方法不然会报错
// ComputedDemo.vue
<template>
<div>
<!-- computed有缓存,只有关联的值发生改变才会重新计算 -->
<p>
double1:{{double1}}
</p>
<p>
<!-- 使用计算属性,进行双向数据绑定,一定要有set和get不然会报错 -->
<input v-model="double2">
</p>
</div>
</template>
<script>
export default {
data(){
return{
num1: 20,
num2: 20
}
},
computed: {
double1(){
return this.num1 * 2;
},
double2: {
get() {
return this.num2;
},
set(val) {
this.num2 = val;
}
}
}
}
</script>
- 侦听属性 watch
- 不支持缓存,只要数据发生变化,就会执行侦听函数
- 侦听属性内支持异步操作
- 侦听属性的值可以是一个对象,接受handler回调,deep,immediate三个属性
<template>
<div>
<input type="text" v-model="name">
<input type="text" v-model="info.city">
</div>
</template>
<script>
export default {
data(){
return{
name: "milo",
info: {
city: "厦门"
}
}
},
created() {
console.log(this.name);
this.name = "test";
},
watch: {
name(oldVal, val){ // 监听原始值变量,oldVal变化前的值,val变化后的值
console.log('watch name', oldVal, val);
},
info: {
handler(oldVal, val){
console.log('watch info', oldVal, val) // 引用值,拿不到修改前的值
},
deep: true, // 深度监听
immediate: true // 首次执行也监听
},
'info.city': function(){ // 监听属性
console.log(this.info.city)
}
}
}
</script>
12. $nextTick
Vue的响应式并不是在数据发生变化之后就立即更新DOM,vm.$nextTick是在下次Dom更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。
- 如果你想在created内操作dom可以使用$nextTick方法
13. Vue双向数据绑定的原理
Vue采用数据劫持 + 订阅发布模式实现双向绑定。通过Object.definedProperty()来为组件中data的每个属性添加get和set方法,在数据变动时,触发set里相应的监听回调函数,将变动信息发布给订阅者,订阅者重新执行render函数完成更新。
- 组件初始化时:
- a. 创建一个dep对象作为观察者(依赖收集、订阅发布的载体)
- b. 通过Object.definedProperty()方法对data中属性添加getter和setter方法;调用getter时,去dep(观察者对象)里注册函数;调用setter时,便通知刚注册的函数。
- 组件挂载时:
- a. compile解析模板,将其中的变量替换成数据。然后初始化渲染页面视图,并进行dom监听和事件绑定。后续一旦数据发生变化,便会更新页面,页面发生变化也会相应发布变动信息;
- b. 组件同时会定义watcher类作为订阅者,watcher可以视作dep和组件之间的桥梁。其在实例化时会向dep中添加自己,同时自身又有一个update方法,待收到dep变动通知时,便会调用自己的update方法,触发compile中相应的函数完成更新。
14. Vue渲染和更新的过程
- 渲染过程
- 解析模板为render函数
- 触发响应式,通过getter和setter监听data属性
- 执行render函数,生成 vnode,然后patch(elem, vnode)生成真实的dom
- 更新过程
- 数据变化,触发setter
- 重新执行render函数,生成newVnode
- 重新patch(vnode, newVnode)
- vue组件是异步渲染 vue在更新Dom时是异步执行的。只要侦听到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入队列中一次。可以避免不必要的计算和DOM操作。
15.虚拟DOM的优缺点
优点:
-
保证性能下限: 虚拟DOM可以经过diff找出最小差异,然后批量进行patch,这种操作虽然比不上手动优化,但是比起粗暴的DOM操作性能要好很多,因此虚拟DOM可以保证性能下限
-
无需手动操作DOM: 虚拟DOM的diff和patch都是在一次更新中自动进行的,我们无需手动操作DOM,极大提高开发效率
-
跨平台: 虚拟DOM本质上是JavaScript对象,而DOM与平台强相关,相比之下虚拟DOM可以进行更方便地跨平台操作,例如服务器渲染、移动端开发等等 缺点:
-
无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化,比如VScode采用直接手动操作DOM的方式进行极端的性能优化