1.说一下你对MVVM原理的理解
1.理解:
- MVVM即是model,view,viewmodel
2.说一下vue响应式数据的原理
1. 核心点:
- object.defineProperty
2. 理解:
- 默认vue在初始化数据时,会给data中的属性使用object.defineProperty重新定义所有的属性,当页面获取到对应属性时,会进行依赖收集(收集当前组件的watcher),如果属性发生变化会通知相关依赖进行更新操作
3.原理:
3.说一下vue中如何检测数组的变化
1. 理解:
- 使用了数组劫持的方式,重写了数组的方法
- vue将data中的数组,进行了原型链的重写。指向了自己定义的数组原型方法,这样当调用数组api时,可以通知依赖更新。如果数组中包含引用类型,会对数组的引用类型再次进行监控。
2.原理:
- 源码里面只拦截了数组的七种方法,因为只有这七种方法会改变原数组
- 七种方法:push,pop,shift,unshift,splice,sort,reverse
4.说一下为何Vue采用异步渲染
1. 理解:
- vue是组件更新
- 如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染,为了性能考虑,vue会在本轮数据更新后,再去异步更新视图
2. 原理:
5.说一下nextTick实现原理
1. 理解:
- nextTick方法主要是使用了宏任务和微任务,定义了一个异步的方法,多次调用nextTick方法会将方法保存在队列中,通过这个异步方法清空当前的队列,所以nextTick方法实际上就是异步方法
- 一般会使用nextTick保证当前视图渲染完成
- flushCallbacks
2. 原理:
6.说一下Vue中的computed特点
1. 理解:
- 计算属性是具备缓存的,只有依赖的属性发生变化才会更新视图
2. computed和watch的区别
[www.cnblogs.com/jiajialove/…]
3. 原理:
7.说一下Vue中的watch中的deep:true是如何实现的
1. 理解:
- 当用户设置watch:true时,如果当前的组件是数组类型,对监控每一项,将当前的watcher存到依赖中,这样数组中的对象变化也会通知数据更新
2.原理:
8.说一下Vue中的生命周期
1. 生命周期图例
2. 生命周期
9.说一下Vue请求接口放在哪个生命周期
1. 理解:
- 在created的时候,视图中的dom还没有渲染出来,所以此时去操作dom节点,无法找到相关的元素
- 在mounted中,因为此时dom已经渲染出来了,所以可以直接操作dom节点
- 一般情况下,都放在mounted中,保证逻辑的统一性,因为生命周期是同步执行的,ajax是异步执行的
- 服务端不支持mounted的写法,所以服务端一般放在created中
10.说一下何时需要使用beforeDestory
1. 理解:
- 可能在当前页面中使用了$on方法,那需要在组件销毁前解绑。
- 清楚自己定义的定时器
- 解绑事件的绑定,例如scroll等等
11.说一下Vue模板中的编译原理
1. 理解:
- 将template转化成render函数
- ast语法树
- 模板引擎的实现:with + new Function()
12.说一下v-if和v-show的区别
1.v-show:通过display:none和display:block之间切换
- 1.切换时需要删除,插入节点开销大
- 2.但是在初始化的时候,如果条件是false,是不会插入节点渲染的会节约性能
- 总结:如果不是频繁的切换,渲染时条件渲染使用v-if
2. v-if:通过dom节点插入。删除来实现切换
- 1.有更高的初始渲染开销,就算是false也会渲染
- 2.但是在切换的时候只是改变样式,消耗少
- 总结:在频繁切换的时候用v-show
13.说一下v-if和v-for为什么不能连用
- v-for的优先级大于v-if
- 连用每次循环都会使用一次v-if,性能不好
- 可以在v-for外层加一个div或者template来使用v-if
14.说一下如何用Vnode描述一个dom结构
15.说一下Vue中的diff算法原理
1. 理解:
- 1.先同级比较,在比较子节点
- 2.先判断乙方有儿子一方没儿子的情况
- 3.比较都有儿子的情况
- 4.递归比较子节点
16.说一下v-for中为什么要有key
1. 理解:
- 唯一标志,不加的话删除会出错
- 尽量不要使用索引作为key,不唯一
17.说一下你对keep-alive的理解
1. 理解:
- keep-alive缓存不活动的组件的状态
2.作用:
- 避免多次重复渲染降低性能
3.知识点:
- include: 匹配组件被缓存
- exclude: 和1相反,除了...都被缓存
- max: 数字,最多可以缓存几个组件
- 给Router路由,缓存部分页面,访问使用$route.meta.keepAlive
// app.vue
<template>
<!-- vue2写法 -->
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
<!-- vue3写法 -->
<router-view v-slot = "{ Component }">
<keep-alive>
<component :is="Component" v-if="$route.meta.keepAlive"></component>
</keep-alive>
</router-view>
<router-view v-slot = "{ Component }">
<component :is="Component" v-if="!$route.meta.keepAlive"></component>
</router-view>
</template>
<style lang="scss">
#app {
text-align: center;
}
</style>
18.说一下判断空对象的方法
1. json.stringify
Json.stringify(obj) === '{}'
返回值是true或false
2. for...in
function hasObj(obj) {
for (let key in obj) {
return false // obj不是空的返回false
}
return true
}
3.Object.getOwnPropertyNames
// Object.getOwnPropertyNames
// 获取到对象中的属性名,存到一个数组中
var obj = {
name: '棠梨煎雪1226'
}
let res = Object.getOwnPropertyNames(obj)
// ['name']
// 判断数组长度是否为0,即可判断对象是否为空
console.log(res.length === 0) // 是true还是false
4.Object.keys
// Object.keys
// 获取对象中所有可枚举的字符串的数组
var obj = {
name: '棠梨煎雪1226'
}
let res = Object.keys(obj)
// ['name']
// 判断数组长度是否为0,即可判断对象是否为空
console.log(res.length === 0) // 是true还是false
5.hasOwnProperty
// hasOwnProperty
// 检测属性是否在对象实例中
function hasObj(obj) {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
return false
}
}
return true
}
19.说一下vue插槽slot
1.默认插槽
- 直接留个solt即可,在组件内写内容
2.具名插槽
父组件:
第一种:<template #tljx>
第二种:<template v-slot:tljx>
子组件
<slot name="tljx">
3.作用域插槽
子组件里面的东西放在父组件使用
子 ----> 父
父组件:
<template v-solt:default="子组件传的值/tljx">
子组件:
<slot v-bind:tljx="定义的数据/要传过去的数据"
20.Vue异步组件,按需加载
1.vue.component
父组件:
引入子组件渲染:
<children></children>
第一种:
components:{
children:()=>import ('./children')
}
第二种:
const children = () => {
component:import ('./children')
}
components:{
children
}
2.is
封装多个子组件的思想
通过传不同的值来渲染不同的组件
<component :is="COMPONENT_NAME"> </component>
COMPONENT_NAME,动态值