1.Object.protptype.toString.call()
每一个Object对象都有toString方法会返回【object type】需要用call来指向执行上下文
2.观察者模式和订阅-发布模式的区别
观察者模式中主体和观察者之间是相互感知的。订阅发布模式是通过第三方调动相互无感知的。
3.为什么 Vuex 的 mutation 中不能做异步操作
无法捕获异步结果
4.组件为何不可以修改父组件传递的 Prop
单向数据流,易于监测数据的流动,出现了错误可以更加迅速的定位到错误发生的位置。
5.call 和 apply 的区别是什么,哪个性能更好一些
区别:第一个参数都是this,第二个参数不同apply是传入一个数组,call从第二个开始传入参数是不固定的,都会传给函数
性能:call比apply的性能要好,平常可以多用call, call传入参数的格式正是内部所需要的格式
6.vue的响应式原理objec.defineproperty有什么缺点。vue3.0中为何要更换为Proxy。
<1>Object.defineProperty无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
<2>Object.defineProperty只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
<3>Proxy不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
7.vue双向数据绑定原理
通过object.definproperty()重新定义了数据获取属性getter和设置属性setter来实现的
8.vue如何进行依赖收集的
Vue初始化的时候,挂载之后会进行编译。生成renderFunction。
取值的时候搜集watcher,放进dep
更改的时候就会通知watcher去更新视图
9.Vue的生命周期
beforeCreate 实例初始化之后 *(数据观测observer和event,watcher事件调用之前)
created 实例创建完成 数据观测,属性和方法的运算,watch、event回调,
e
l
未
生
成
b
e
f
o
r
e
M
o
u
n
t
e
挂
载
之
前
调
用
m
o
u
n
t
e
d
e
l
被
v
m
.
el未生成 beforeMounte 挂载之前调用 mounted el被vm.
el未生成beforeMounte挂载之前调用mountedel被vm.el替换并挂载到实例之后
beforeUpdate 数据更新前 Dom重新渲染和打补丁之前
update 数据更新后
beforDestrouy 实例销毁前
destrouyed 实例销毁后
10.Vue的组件中data为什么是一个函数?
为了防止两个组件的数据产生污染。如果是对象的话,会在合并的时候指向同一地址。函数的话合并会产生两个空间。
11.nextTick的原理
nextTick是一个微任务在下次Dom更新循环结束后执行
可以用于获取更新后的Dom
Vue中的数据更新是异步的,nextTick可以保证用户定义的逻辑在更新后执行
12.计算属性和监听属性的区别
computed计算属性是有缓存的,依赖的值不发生变化对其取值时计算属性不会重复执行
watch监听属性是监控值的变化,当值发生改变的时候就会调用回调函数
13.diff算法原理
diff算法是平级比较,采用深度递归+双指针
先比较两个节点是否相同
相同节点比较属性,复用老节点
先比较儿子节点,考虑老节点和新节点儿子的情况
优化比较:头头 尾尾 头尾 尾头
比对查找,进行复用
14.使用key的作用和原理
key的作用主要是为了高效更新虚拟DOM(精准判断两个节点是否是同一个,就地复用)
没有key在更新列表时会出现一些隐蔽bug
key 是给每一个 vnode 的唯一 id,依靠 key,我们的 diff 操作可以更准确、更快速
更准确 : 因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确,如果不加 key,会导致之前节点的状态被保留下来,会产生一系列的 bug。
更快速 : key 的唯一性可以被 Map 数据结构充分利用
15.组件通信方式
props和$emit
parent和children
provide和inject
$ref获取子组件
eventBus
Vuex
16.v-if和v-for的优先级
vue2.0 v-for的优先级比v-if高
vue3.0 v-if的优先级比v-for高
17.vue双向数据绑定的原理和实现方式
vue双向数据绑定是通过数据劫持结合发布者订阅者模式实现的
18.vue的修饰符
stop
prevent
captrue
self
once
passive
right
center
middle
alt
19.vue注册自定义指令
directive方法注册指令第一个参数是指令名第二个是触发后执行的方法
20.vue路由钩子执行顺序
失活组件调用beforeRouteLeave
全局beforeEach
重用组件调用beforeRouteUpdata
路由配置beforeEnter
被激活调用beforeRouteEnter
全局beforeResolve
全局afterEach
21.vue响应式原理、
通过object.defineproptype()给data中每个数据添加get和set在添加dep和watcher完成依赖收集和派发更新,最后通过diff算法对比更新新老vnode,通过patch更新实时DOM
22.computed 的实现原理
computed 本质是一个惰性求值的观察者computed watcher。其内部通过 this.dirty 属性标记计算属性是否需要重新求值。
当 computed 的依赖状态发生改变时,就会通知这个惰性的 watcher,computed watcher 通过 this.dep.subs.length 判断有没有订阅者,
有的话,会重新计算,然后对比新旧值,如果变化了,会重新渲染。 (Vue 想确保不仅仅是计算属性依赖的值发生变化,而是当计算属性最终计算的值发生变化时才会触发渲染 watcher 重新渲染,本质上是一种优化。)
没有的话,仅仅把 this.dirty = true (当计算属性依赖于其他数据时,属性并不会立即重新计算,只有之后其他地方需要读取属性的时候,它才会真正计算,即具备 lazy(懒计算)特性。)
23.watch 的理解
watch没有缓存性,更多的是观察的作用,可以监听某些数据执行回调。当我们需要深度监听对象中的属性时,可以打开deep:true选项,这样便会对对象中的每一项进行监听。这样会带来性能问题,优化的话可以使用字符串形式监听
24.keep-alive实现原理
定义:keep-alive组件接受三个属性参数:include、exclude、max
include 指定需要缓存的组件name集合,参数格式支持String, RegExp, Array。当为字符串的时候,多个组件名称以逗号隔开。
exclude 指定不需要缓存的组件name集合,参数格式和include一样。
max 指定最多可缓存组件的数量,超过数量删除第一个。参数格式支持String、Number。
原理:keep-alive实例会缓存对应组件的VNode,如果命中缓存,直接从缓存对象返回对应VNode
LRU(Least recently used)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。(墨菲定律:越担心的事情越会发生)
25.什么是防抖和节流?有什么区别?如何实现?
防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率