react列表组件渲染中key的作用

14 篇文章 0 订阅
7 篇文章 0 订阅

我们在开发react列表组件时,如果遍历项中缺少key,那么就会出现一个警告,a key should be provided for list items,就是当创建一个元素时,必须包含一个特殊的key属性。那么为什么要加这个key,其作用又是什么呢?

首先来看一下官方的解释:
key帮助React识别了哪些元素改变了,如添加或删除,所以需要给列表元素赋予一个唯一的标识

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

一个元素的key一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,使用来自数据 id 来作为元素的 key:

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

当元素没有确定 id 的时候,万不得已你可以使用元素索引 index 作为 key:

const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。当没有添加时,React会使用索引作为key。

感觉官方的不太深入。。。,下面来深入了解一下:
看完上面我们大致了解了key的作用,以及一点点缺少key的弊端,但这只是表面的官方解释,其实最主要的是key在React diff算法来更新虚拟dom节点时的作用!

首先React的dom更新是通过diff算法来比较新旧虚拟节点,来更新节点的,diff算法是什么呢?说简单点就是通过遍历新旧虚拟dom节点的所以子元素,来判断节点更新状态,但React中的diff又不同于传统的diff算法,在React中将传统的diff算法O(n^3)的复杂度转换为O(n) 的复杂度,其实就是在对比当前节点时,如果新旧虚拟节点不同,React直接删除前面的节点,然后创建并插入新的节点。如果相同,便会通过唯一标识key的快速定位节点比较,从而減少dom操作次数,提高性能,具体可以参考InfoQ相关了解(https://www.infoq.cn/article/react-dom-diff)。

到现在可能有些人会提出疑问,diff通过key来查找比较,每次更新都不用找到可复用的节点,所以需要创建、销毁虚拟节点,在dom里操作添加移除节点会影响性能。确实在不添加key的列表数据要比添加key的列表渲染速度要快,但是这仅仅限于无状态组件,但是我们在实际开发中大多数列表组件都会有自己的状态,如果没有这个唯一标识key,假如数据列表均为未标记,点击第一项标记为已标记,切到第二项便会直接变为已标记,因为复用了组件,保留了之前的状态。所以我们加上这个唯一key,就会避免这样的问题,保证组件列表项的状态正确。

最后总结一下key的作用:

key是给每一个虚拟dom的唯一id,可以依靠key,更准确, 更快的拿到旧虚拟dom中对应的新虚拟dom节点。

有状态组件

  • 更加准确:
    添加key就不是就地复用了,可以保证自身状态正确。所以会更加准确。
  • 更快速:
    利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值