vue为啥不建议用index作为key值
key的作用是为了复用组件,减少对dom的操作,如果key值不准确,index的操作进入了vue的sameNode函数(即头头相同),那么vue可能会复用了错误的节点,从而进入patchNode()这个函数,然后去更新节点的属性,样式,事件绑定,指令这些重量级的操作(可以理解为加重了对dom操作,性能不友好);相对的,如果key值是复用了正确的节点,那么在patchNode这个函数中,oldNode===newNode,直接return,不用操作,性能大大提升。
vue为啥异步更新
vue的更新都是由watcher这个代理更新的,而这个watcher在vue渲染的时候已经被收集到了dep里面,通过dep.notify同步触发了watcher的update(),进而生成一系列的watcher的队列,每次用户更新数据的时候,可能更新一次或者多次,就会不断push进来很多watcher,vue对重复的watcher做了处理之后,把watcher的队列放在了当前执行栈的微任务队列里面或者宏任务队列里面(即异步),这样做了为了解决用户的不断或者重复的操作后,拿取用户最后的操作,然后在下一个执行栈中执行,就不会由于用户的多次操作而进行多次更新,我异步更新,就只会更新一次。
如何理解computed和method
计算属性本质上就是一个computed wachter,vue初始化的时候,在initState函数里面会初始化了computed(即vue执行渲染,当前watcher为渲染watcher)
computed初始化的过程:
-
遍历了computed对象,给每个属性生成了new watcher(实际是computed watcher)实例,同时在这个watcher里面new Dep了一个实例,this.dep = new Dep()。
-
渲染watcher读取了计算属性,当前的渲染watcher就订阅了这个属性的dep,即上一步所实例的dep,dep也收集了当前的渲染watcher。
3.然后执行了watcher.evaluate(),此时的watcher是computed watcher,即执行这个属性的getter函数(return this.a + 1),比如:
data(){
return{
a:1
}
},
computed:{
sum:function(){
return this.a + 1
}
}
发现当前属性依赖了a这个响应式属性,根据响应式原理,a被访问时,也生成了a的dep实例,被当前的watcher订阅,即computed watcher,a的dep实例也收集了computed watcher到dep的sub数组中。
当a发生变化时,通知computed watcher更新,此时这个computed watcher的dirty属性为true,然后computed watcher检查自身this.dep(即当前计算属性,例子中指sum生成的dep有谁订阅),发现渲染watcher在订阅它,于是调用this.dep.notify(),通知渲染watcher更新数据。
computed watcher 本身是有一个开关的,dirty属性,当dirty为true时,即数据脏了,需要更新,什么时候数据脏了,例子中a发生变化了,此时dirty需要设置为true,当计算属性更新完后才将dirty变成false。
总结:计算属性是依赖数据更新的,当所依赖的数据发生变化时(dirty为true)才去执行更新操作,否则不会再去执行调用,直接返回之前值即可。而method每次调用时就执行。