react为什么不推荐使用index作为key

1.旧的虚拟dom和新的虚拟dom对比,首先看他们的key是否相同
2.相同继续对比他们的内容,不同生成新的真实dom进行替换
3.如果内容和key都相同,复用旧的真实dom 不做改变

那么如果我们使用遍历时候自动生成的index作为每个节点的key可能会出现什么问题呢? 下面放个小案例

首先,初始时我们进行遍历persons

他会是这样一个过程,源数据

persons: [
{ id: 1, name: “张三”, age: 15 },
{ id: 2, name: “李四”, age: 16 },
],

生成的真实dom节点

<ul>
      <li key="0">张三--15</li>
      <li key="1">李四--16</li>
    </ul>

然后我们在这个名单前面插入一个{id:3,name:‘王五',age:14}的数据会变成这样子

<ul>
   <li key="0">王五--14</li>
      <li key="1">张三--15</li>
      <li key="2">李四--16</li>
    </ul>

通过上面的更新可以发现 王五将之前张三的key给占用了
也就是说当我进行更新这一过程首先新的虚拟dom

<li key="0">王五--14</li>

和旧的虚拟dom

<li key="0">张三--15</li>

进行比较 新的dom先比较key两人相同,在比较内容一个是王五–14 一个是张三15 ,内容发生变化了,这时就会进行使用新的虚拟dom生成新的真是dom重新渲染页面,而且不仅是之前的张三受影响需要重新生成,后面的李四也要被张三进行替换在生成一个新的内容为张三的真实dom,这样就会导致所有的dom都要重新生成重新渲染,导致性能下降

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>

    <div id="root"></div>
    <script type="text/babel">
      let root = document.getElementById("root");
      class App extends React.Component {
        constructor(props) {
          super(props);
        }
        state = {
          persons: [
            { id: 1, name: "张三", age: 15 },
            { id: 2, name: "李四", age: 16 },
          ],
        };
        handle = () => {
          const { persons } = this.state;
          const p = {
            id: 0,
            name: "王五",
            age: 14,
          };
          this.setState({
            persons: [p, ...persons],
          });
        };
        render() {
          return (
            <div>
              <button onClick={this.handle}>点击添加</button>
              <ul>
                {this.state.persons.map((person, index) => (
                  <li key={index}>
                    {person.name}--{person.age}
                  </li>
                ))}
              </ul>
            </div>
          );
        }
      }
      ReactDOM.render(<App name="hell" />, root);
    </script>
  </body>
</html>

试想一下经过上面的推导致,如果我们使用id作为唯一的key值会怎么样呢

更新前

<ul>
      <li key="1">张三--15</li>
      <li key="2">李四--16</li>
    </ul>

更新后

<ul>
   <li key="0">王五--14</li>
      <li key="1">张三--15</li>
      <li key="2">李四--16</li>
    </ul>

这次 虽然王五插入的还是张三的前面但是只对比了一次 王五和上面是否有一样的key=0的节点 ,没有生成新的真实dom进行渲染,而张三和上面key=1的进行对比,发现上面有一个key=1的节点,然后再对比他们的内容是否相同,发现内容也相同,那么就可以复用旧的真实dom,节约性能

到此这篇关于react为什么不推荐使用index作为key的文章就介绍到这了,更多相关react index作为key内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2021-07-21

vue2.0移除或更改的一些东西(移除index key)

一.vue2.0移除了$index和$key 虽然说现在很多文章说他们的代码是vue2.0版本的,但是有一些仔细一看,发现并不全是2.0版本,有些语法还是1.0的版本,比如这个$index,$key,这两个压根就不是2.0的写法,2.0早就把这两个给删除了,我们先来看看之前的列表渲染是怎么写的 <template> <div class="hello"> <ul> <li v-for="item in list">{{

详解为什么Vue中不要用index作为key(diff算法)

前言 Vue 中的 key 是用来做什么的?为什么不推荐使用 index 作为 key?常常听说这样的问题,本篇文章带你从原理来一探究竟. 另外本文的结论对于性能的毁灭是针对列表子元素顺序会交换.或者子元素被删除的特殊情况,提前说明清楚,喷子绕道. 本篇已经收录在 Github 仓库,欢迎 Star: https://github.com/sl1673495/blogs/issues/39 示例 以这样一个列表为例: <ul> <li>1</li> <li>

vue中使用v-for时为什么不能用index作为key

结论: 更新DOM的时候会出现性能问题 会发生一些状态bug React 中的 key 也是如此 如果已经了解 为什么要用key,可以通过目录直接跳到下一节. 为什么要用key? Vue 和 React 都实现了一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面.而隐藏在背后的原理便是其高效的Diff算法. Vue 和 React 的虚拟DOM的Diff算法大致相同,其核心是基于两个简单的假设: 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构. 同一

Vue中消息横向滚动时setInterval清不掉的问题及解决方法

最近在做项目时,需要进行两个组件联动,一个轮询获取到消息,然后将其传递给另外一个组件进行横向滚动展示,结果滚动的速度越来越快.这里记录一下来提醒自己.消息滚动的代码在最下面,方便下次使用. 问题背景: 最近在做一个需求,组件A获取消息采用的是轮询,组件A获取到新的消息后,将组件A中的消息传递给另外一个组件B,当组件B接收到消息时就让消息在页面上滚动播放. 实现思路: 这个项目应用的框架为VUE,当组件A获取到新的消息之后,就触发中央事件总线,在组件B中进行事件监听,将其添加进入一个数组,当判断定

vue中使用element组件时事件想要传递其他参数的问题

在使用element的上传组件时在一下几个钩子中传递其他参数 图中是文件上传时的几个钩子,参数为文件或文件列表或者其他参数,但是现在我想在原有参数上传递其他参数.比如我想在on-success的钩子中传递一个自定义参数i,原本是这样写的: :on-success="handleSuccess(i)" //handleSuccess是一个方法 但是发现这样写取不到自身原来的参数,后来在网上找到了一个比较好的方法,如下: :on-success="(value)=> han

在Vue中获取组件声明时的name属性方法

在实际开发中,我们可能需要拿到组件声明时创建的一些属性,比较典型的话就是name属性,在实际开发中需要定位问题时,需要找到是哪一个组件,但是我们总不可能写代码的时候去先找到组件的name属性,然后复制粘贴,作为参数传给函数吧. 例如: catchError('componentsName', 'errorDescription') 太傻了. 解决办法,获取到组件的this,然后利用this去拿到组件的name属性,这样的话,代码就可以这么写: catchError.call(this, 'err

浅谈vue中组件绑定事件时是否加.native

组件绑定事件时 1. 普通组件绑定事件不能添加.native, 添加后事件失效 2. 自定义组件绑定事件需要添加.native, 否则事件无效 <template> <!-- <mt-field label="用户名" placeholder="请输入用户名"></mt-field> --> <input type="text" @keyup.native="show($event)

Vue中关闭弹窗组件时销毁并隐藏操作

背景:在dialog弹窗组件中执行mounted钩子,将数据初始化,等取消关闭弹窗后,发现mounted钩子不执行 原因:在vue的生命周期中,在页面初始化的时候mounted只会执行一次,关闭弹窗页面并没有销毁,所以不会再次执行 <select-experience-group :trialMoneyRecordID=trialMoneyRecordID :showExperienceGroup='showExperienceGroup' @closeCover="handleExper

在Vue中使用echarts的实例代码(3种图)

前言 公司的项目中需要对数据做可视化处理,高级点的D3.js目前还没接触到,因此选用了大众化的Echarts, 在vue的生态系统中已经有实现好的vue-echarts,但是使用现成的就意味着必须使用它定制好的数据结构,我也没办法对他进行一些修改.我个人也偏向于原生JS编程,因此没有采用,而是自己在vue中实现了对数据的可视化处理,先来看看效果图 以下数据已做脱敏处理 这是目前用到的三种图. 可以看到,我在图表的外部添加了标题及说明,以及右侧的选择框组件,视图可以根据选择的不同,图表进行动态切换

Vue中"This dependency was not found"问题的解决方法

今天在初始化项目中,出现了一个奇怪的情况:明明路径是对的,但是编译的时候,一直报"This dependency was not found"的错. 代码如下: import Vue from 'vue' import App from './App' import router from './router' import 'common/stylus/index.styl' /* eslint-disable no-new */ new Vue({ el: '#app', rend

在 Vue 中使用 JSX 及使用它的原因浅析

本文 GitHub https://github.com/qq44924588... 上已经收录,更多往期高赞文章的分类,也整理了很多我的文档,和教程资料.欢迎Star和完善,大家面试可以参照考点复习,希望我们一起有点东西. Vue.js 具有简单的 API 和几个选项,可用于在我们的组件中定义HTML模板. 我们可以使用 <template> 标签选项,在根组件实例上定义 template 属性,或者使用单文件组件. 上面的选项很棒并且可以完美地工作,但是,在您的应用程序的生命周期中,有时会

vue中提示$index is not defined错误的解决方式

今天学习Vue中遇到了一个报错信息:$index is not defined,是我写了个for循环在HTML中,然后是因为版本的问题 下面是解决方法: 原来的是 v-for="person in items" v-on:click="deletePerson($index)"//这个仅仅适用于1.0版本,不要采坑了同学们 这个在Vue1.0版本中式适用的可以直接使用$index,但是在2.0是不适合的 在Vue 2.0版本中获取索引我们需要通过 v-for = &