合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
首先关于 key,需要掌握的是那个知识点 一:为什么要使用 key 二:使用 index 做 key 存在的问题 三:如何正确的选择 key ## 1. 为什么要使用 key * 识别元素的状态,是添加或展示 * 不指定显式的 key时,默认使用索引用作为key **如果列表项目的顺序可能会变化,不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题** ## 2. 为什么由数组动态创建的组件需要用到key呢 ![](https://img.kancloud.cn/bf/7d/bf7dc22be1ec2ab728d509693749423c_1472x908.png) 从 babel 转换的代码来看,其他元素不管是state 还是 props的改变,它始终占据着一个createElement 的固定位置,这个位置就是天然的key 而数组由于是动态的 所以子组件的位置有可能发生改变,这样加一个 key react 就会知道是那个发生改变 ## 3. diff 算法 之 key(dom 节点是否可以复用) ~~~ function reconcileSingleElement( returnFiber: Fiber, currentFirstChild: Fiber | null, element: ReactElement ): Fiber { const key = element.key; let child = currentFirstChild; // 首先判断是否存在对应DOM节点 while (child !== null) { // 上一次更新存在DOM节点,接下来判断是否可复用 // 首先比较key是否相同 if (child.key === key) { // key相同,接下来比较type是否相同 switch (child.tag) { // ...省略case default: { if (child.elementType === element.type) { // type相同则表示可以复用 // 返回复用的fiber return existing; } // type不同则跳出循环 break; } } // 代码执行到这里代表:key相同但是type不同 // 将该fiber及其兄弟fiber标记为删除 deleteRemainingChildren(returnFiber, child); break; } else { // key不同,将该fiber标记为删除 deleteChild(returnFiber, child); } child = child.sibling; } // 创建新Fiber,并返回 ...省略 } ~~~ ## 3. 使用 index 做 key 存在的问题 1. 对于单纯的展示组件来说,当数据的源顺序发生改变的时候,会有性能变差问题 ![](https://img.kancloud.cn/e6/7a/e67ac4c11257b8107916a525ce5ed913_822x580.png) 2. 像 input 这样 用户可以随意改值的组件, 使用 index 作为 key 会有组件状态的问题 ## 4. 推荐使用 index 的情况 1. 如果是分页渲染一个列表,点击会翻页