如何正确理解vue中的key详解

就目前所了解的情况,key的作用有以下这些。

v-for遍历时,用id,uuid之类作为key,唯一标识节点加速虚拟DOM渲染

响应式系统没有监听到的数据,用+new Date()生成的时间戳作为key,手动强制触发重新渲染

场景一大同小异司空见惯,场景二是下面这样的:

<div :key="rerender"> <span>Hello Vue.js !</span> <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent> </div> refresh(){ this.rerender = + new Date(); }

那么vue中key的相关知识点到底是怎样的呢?

官方API知识点

上面2个使用场景背后的原理是什么?

除key外,还有其它强制更新DOM的方法吗?

参考资料

官方API知识点

在Vue.js中,key是6个特殊属性key, ref, is, slot, slot-scope, scope其中之一。

key的值可以是number,也可以是string。

key主要作用于Vue的virtual DOM算法,在diff new nodes list和old nodes list时,作为识别VNode的一个线索。

如果不用key,Vue会用一种算法:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。

如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。

拥有同一个parent的children必须有unique keys。重复的key的导致render error。

最常用的用法一:v-for

<ul> <li v-for="item in items" :key="item.id">...</li> </ul>

最常用的用法二:强制替换element或者component

触发组件的lifecycle

触发transition

<transition> <span :key="text">{{ text }}</span> </transition>

text发生变化时,<span>会被replaced,而不会patched,因此transition会被触发。

我的理解:

text变化时,span的key发生了变化,也就是说曾经拥有了旧key的span不再出现了,当拥有新值的text作为key时,拥有了新key的span出现了,那么旧key span会被移除,旧transition也会移除,新key span触发渲染,新transition触发。

上面2个使用场景背后的原理是什么?

结合官方API的知识点,现在再来回顾文章开头提出的场景。

场景一:v-for遍历时,用id,uuid之类作为key,唯一标识节点加速虚拟DOM渲染

答案:

如果不用key,Vue会用一种算法:最小化element的移动,并且会尝试尽最大程度在同适当的地方对相同类型的element,做patch或者reuse。

如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。

场景二:响应式系统没有监听到的数据,用+new Date()生成的时间戳作为key,手动强制触发重新渲染

<div :key="rerender"> <span>Hello Vue.js !</span> <complexComponent :propObj="propObj" :propArr="propArr" ></complexComponent> </div> refresh(){ this.rerender = + new Date(); }

答案:

如果使用了key,Vue会根据keys的顺序记录element,曾经拥有了key的element如果不再出现的话,会被直接remove或者destoryed。

refresh方法调用后,包含了span和complexComponent的div的key发生了变化,也就是说曾经拥有了旧key的div不再出现了,当拥有新值的rerender作为key时,拥有了新key的div出现了,那么旧key div会被移除,旧span和complexComponent也会移除,新key div触发渲染,新span,带着父组件新propObj和propArr的新complexComponent渲染。

思考:

为什么要叫propObj和propArr?

带着父组件新propObj和propArr的新complexComponent渲染。 为什么要加粗?

由于Vue.js的obj和arr存在无法检测到数据变化的情况,obj是属性的新增和删除(原因是新增和删除都没有触发setter,watcher未告诉外界更新),arr则是数组内元素重新赋值或者修改length属性(原因是没有使用改变数组本身的方法,没有触发数组原型链拦截器,watcher未告诉外界更新)。

所以!通过赋予新key的方式,移除旧key div,渲染新key div,propObj和propArr在complexComponent组件内会重新触发一次生命周期,做一次重新渲染。此时父组件的propObj和propArr js变量其实已经获取到新值了,只是没有触发DOM也好,VNode也好的重新渲染。需要通过刷新key去force update,说到forceUpdate,可以通过$forceUpdate()去手动强制更新DOM。

除key外,还有其它强制更新DOM的方法吗?

场景:父组件修改传递给子组件的数据,数组数据的更新没有按照this.$set去更新。该怎么办?

this.productImages.forEach((product) => { if (product.productId in this.productsState) { product.status = this.productsState[product.productId]; } });

不使用this.$set去赋值数据的不能rerender的原因是什么?

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/2c1ca9ccd4131957f1f6fec82ae3a79e.html