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可以正确的删除所有节点。

相关推荐
前端大波1 小时前
前端面试通关包(2026版,完整版)
前端·面试·职场和发展
Cobyte2 小时前
3.响应式系统基础:从发布订阅模式的角度理解 Vue2 的数据响应式原理
前端·javascript·vue.js
军军君012 小时前
Three.js基础功能学习十八:智能黑板实现实例五
前端·javascript·vue.js·3d·typescript·前端框架·threejs
禅思院3 小时前
前端架构演进:基于AST的常量模块自动化迁移实践
前端·vue.js·前端框架
许杰小刀3 小时前
FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南”
前端·vue.js·fastapi
walking9573 小时前
Vue3 日历组件选型指南:五大主流方案深度解析
前端·vue.js·面试
英俊潇洒美少年3 小时前
Vue、React.lazy、React 19 异步组件核心区别
javascript·vue.js·react.js
快乐小土豆~~4 小时前
echarts柱状图的X轴label过长被重叠覆盖
前端·javascript·vue.js·echarts
儒雅的烤地瓜4 小时前
Vue | Vue3中<script setup>用法详解
vue.js·vue3·选项式api·组合式 api·setup方法·<script setup>
小李子呢02114 小时前
前端八股2---Proxy 代理
前端·javascript·vue.js