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

相关推荐
by__csdn13 分钟前
Vue3 setup()函数终极攻略:从入门到精通
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript
一条可有可无的咸鱼1 小时前
企业招聘信息,企业资讯进行公示
java·vue.js·spring boot·uni-app
lionliu05191 小时前
js的扩展运算符的理解
前端·javascript·vue.js
铭哥的编程日记2 小时前
后端面试通关笔记:从真题到思路(五)
面试·职场和发展
前端一小卒3 小时前
一个看似“送分”的需求为何翻车?——前端状态机实战指南
前端·javascript·面试
老前端的功夫3 小时前
Vue 3 vs Vue 2 深度解析:从架构革新到开发体验全面升级
前端·vue.js·架构
xlp666hub4 小时前
C进阶之内存对齐,硬件总线和高并发伪共享的底层原理
面试·代码规范
狗哥哥4 小时前
Vue 3 动态菜单渲染优化实战:从白屏到“零延迟”体验
前端·vue.js
青青很轻_4 小时前
Vue自定义拖拽指令架构解析:从零到一实现元素自由拖拽
前端·javascript·vue.js
xhxxx4 小时前
从被追问到被点赞:我靠“哨兵+快慢指针”展示了面试官真正想看的代码思维
javascript·算法·面试