react渲染列表中的key的作用

这个key首先是只在渲染数组列表的时候会用到。

比如经常遇到的

 如上

没有key的话,会报一个错,那么,我们可不可以使用数组的index作为下标呢?

答案是不推荐。因为在数组项的顺序在插入、删除或者重新排序等操作中会发生改变,此时把索引作为key可能会产生一些微妙的bug。

像下面这种纯div渲染列表是没有问题的,用index作为key

它的列表item是div,纯渲染

 我们再来看看如果列表是非受控元素的情况,把代码改造下

点击事件会触发组件重新渲染

 

 

可以看到,列表渲染出问题了,分析一下这种情况。

setState导致render,div的index不变,所以div不会重新生成,input不受state和props的控制,因此元素的状态不变,所以变化的只有受state影响的上面的{item}。

把key改为item,如下,就没有问题了

 

 

 

这里其实也揭露了一个问题,那就是当key变化的时候,元素会销毁重建,若key不变,则进行更新。

再用通俗的话来说,react会借助key来判断元素是最新创建的还是移动出来的,从而减少不必要的元素渲染(不必要的diff)。key属性帮助react识别唯一的组件,从而可以更高效地更新和重新渲染,key属性有助于确保组件的唯一性,是组件能够正确被复用。

注意,这里还和虚拟dom扯上关系了,要想真正了解key的作用,必须得理解react的虚拟dom以及diff。

  这里先介绍一下vdom,react组件render产生vdom,然后渲染器把vdom渲染出来。state更新的时候,组件会重新render,产生新的vdom,在浏览器平台下,为了减少dom的创建,react会对两次的render结果做diff,尽量复用dom,提高性能。这就是vdom的来由。

  所以key的真正作用,就是在diff过程中,新旧虚拟dom节点,使用key进行对比,而key是保存在一个map里面,使用映射能够很快的找到哪些节点是复用,哪些节点是删除还是新增,速度非常快。比虚拟dom节点全部对比一遍速度要快的多。这就是key最直观的作用,加快diff的性能。

  如果不使用key的话,在对新旧虚拟dom diff的过程中就得所有节点全部对比一遍,浪费性能。没有key的情况,就是旧地复用的问题。 没有key的情况,节点位置不变,但是节点innerText内容更新了。有key的情况下,dom节点位置进行了交换,但是内容没有更新。那么这么来看,确实是有key的时候,更浪费性能一点。但是这也要分场景,只有在最简单的纯列表渲染节点中,可以不用key。但是当你的节点有交互性,或者有状态,比如上例的节点是单选的情况,这种情况就一定需要key了,否则就会出bug。或者当你想要子节点的变化,触发过渡效果时,也需要使用key。

  这里也回答了一个问题,key的作用就是为了vdom节点的复用,如果用Index作为key的话,就会出现上图中的复用错误

 

官网中对于diff有如下规则:

  • 当元素类型变化时,会销毁重建
  • 当元素类型不变时,对比属性
  • 当组件元素类型不变时,通过props递归判断子节点
  • 递归对比子节点,当子节点是列表时,通过key和props来判断。若key一致,则进行更新,若key不一致,就销毁重建

 理解React中key的作用这个问题涉及react渲染机制和diff算法,在state或props变化的情况下,会造成渲 - 掘金 (juejin.cn)

 

posted @ 2024-08-08 21:37  飞向火星  阅读(19)  评论(0编辑  收藏  举报