key可以重复嘛?为什么不使用index做key

先有问题再有答案

  1. diff算法中key有什么用
  2. react或者vue中 key可以重复嘛 重复了会怎样? 为什么?
  3. 为什么不建议使用index作为key?

key有什么用

diff算法中key用于标识当前元素, 目的是实现节点复用, 所以key应该是稳定的、唯一的。

需要注意 节点复用和组件更新的关系

key是节点复用的前提,相同不一定复用,还有层级和类型的限制。不同一定不复用。

组件依赖项(props|state)发生变化 dom就会被更新。

为什么不建议使用index作为key

无论是react还是vue 当index作为key时 不能有效的实现节点复用 导致性能问题。

如图:

我们的期望是实现n1,n2,n3,n4的dom复用 删除n5并新增n6。然而因为使用index作为key所以会复用所有的dom 但是每个组件的内容实际都是不一致的,所以全部dom都需要做更新处理。因此会有性能问题。

key重复会有什么问题

react 示例

javascript 复制代码
import React, { useState } from "react";

export default function MyApp() {
  const [textList, changeTextStr] = useState([1, 2, 3, 4, 4]);

  return (
    <div>
      {textList.map((t) => (
        <div key={t}>{t}</div>
      ))}
      <button
        onClick={() => {
          changeTextStr([5, 6, 7]);
        }}
      >
        change
      </button>
    </div>
  );
}

点击change后

为什么会多一个4?

分析

实际上这是因为react的diff算法导致的。

简单介绍下就是 react在做diff时 需要经过以下步骤

  1. 遍历新旧两个节点相等时 同时下移指针 当遇到两个节点不一致时跳出循环。
  2. 将剩余旧节点的key和对应的节点对象 存储在map中 因为map的key需要唯一 所以相同的key后面的会覆盖前面的 这就导致 实际节点内容为1,2,3,4,4 但是map中存储的只有1,2,3,4 这个4是第二个4.
  3. 然后遍历剩余新节点 如果在map中找到 则节点复用 并标记。
  4. 如果没有找到说明这个节点需要新增
  5. 在遍历map 得到对应的节点 并删除多余的节点 因为map中保留的是key:4 并且是N5节点 所以删除的也是对应的N5节点。

所以最后会导致N4节点被留在了dom树中。

需要注意的以上只是diff算法的简单描述 本文不是讲解diff算法 而是在解决key重复引起的问题。

vue中key重复也会有这个问题嘛?

xml 复制代码
<script setup>
import { ref } from 'vue'

const list = ref([1,2,3,4,4])
const btn = () => {
  list.value = [5,6,7]
}

</script>

<template>
  <div v-for="item in list">{{ item }}</div>
  <div @click="btn">点击</div>
</template>

点击按钮后: 看起来是可以正常显示的 这又是为什么?

分析

与react一样 vue最终的目标也是要做dom复用。所以也需要一个map来标识是否可以复用。只是vue是以新的列表为基础创建一个key&位置的映射表。 key 5 位于新列表第一项 所以是{5:0} 建立完map后 vue会遍历旧节点数组 如果在map中没找到改节点 说明需要删除。 因此vue可以正确的删除所有节点。

相关推荐
Frank学习路上16 小时前
【C++】面试:关键字与语法特性
c++·面试
kisdiem16 小时前
ReAct:让大模型一边推理,一边行动
前端·react.js·前端框架
ShineWinsu16 小时前
对于Linux:线程概念与分页存储管理的解析
linux·运维·服务器·面试·线程·进程·虚拟空间地址
文艺倾年16 小时前
【强化学习】强化学习基本概念,20W字总结(一)
人工智能·python·语言模型·自然语言处理·面试·职场和发展·大模型
尽兴-17 小时前
4.1 智能体核心:Agent、Sub-Agent、ReAct、规划执行
前端·javascript·react.js·agent·react·subagent
万物更新_17 小时前
vue框架
前端·javascript·vue.js·笔记
Asize18 小时前
JavaScript 数据类型解析:从 null 与 undefined 的迷思到栈堆内存真相
前端·javascript·面试
LDX前端校草18 小时前
position属性值及用法
前端·javascript·面试
hzhsec20 小时前
启明星辰(安全服务实习生)面试题
网络安全·面试
AI人工智能+电脑小能手21 小时前
【大白话说Java面试题 第115题】【并发篇】第15题:说一下悲观锁和乐观锁的区别?
java·开发语言·面试