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

news/2024/7/9 23:54:30 标签: react, vue, diff算法, key的唯一性, 前端

reactdiffdom_1">reactdiff算法执行新旧虚拟dom替换的一个流程

1.旧的虚拟dom和新的虚拟dom对比,首先看他们的key是否相同
2.相同继续对比他们的内容,不同生成新的真实dom进行替换
3.如果内容和key都相同,复用旧的真实dom 不做改变
那么如果我们使用遍历时候自动生成的index作为每个节点的key可能会出现什么问题呢? 下面放个小案例
首先,初始时我们进行遍历persons
他会是这样一个过程,源数据
1.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,节约性能

http://www.niftyadmin.cn/n/1206082.html

相关文章

【云扩RPA】Quiz_XPath

当XPath属性值和其他属性值均为选中状态时&#xff0c;运行时下列哪项说法正确&#xff1f; 若XPath属性值和其他属性值有冲突&#xff0c;则报错若XPath属性值和其他属性值有冲突&#xff0c;按照排列顺序&#xff0c;取其他属性值来定位元素若XPath属性值和其他属性值有冲突…

js实现函数的call方法(非es6)

call方法 这个问题当初刚学js的时候就很困扰&#xff0c;fn.call(this,a,b,…) 如果不用es6的解构方法&#xff0c;this后面的参数到底是如何传递给另外一个函数作为多个参数呢&#xff0c;今天回看红宝书突然回想起了这个问题&#xff0c;也找到了答案&#xff0c;不多说直接…

将以上文件名中的oldboy全部改成oldgirl(用for循环实现),并且html改成大写。

第一种方法&#xff1a;#!/bin/bash cd /oldboy for i in ls dorename oldboy oldgirl $i |rename html HTML $i done第二种方法&#xff1a;#!/bin/bash cd /oldboy for i in ls do mv $i echo $i|sed -e s#oldboy#oldgirl#g;s#html#HTML#g done转载于:https://blog.51cto.com…

【云扩RPA】XPath

增加XPath属性 当某些元素难以定位或者定位不稳定时&#xff0c;可以通过增加XPath属性来解决这一问题。当使用XPath时&#xff0c;XPath所在的节点层级将通过XPath属性值来定位&#xff0c;此节点层级的其他属性值将不会发生效力&#xff08;即使其复选框为选中状态&#xff…

react兄弟传值,使用发布订阅模式

react兄弟传值&#xff0c;以及跨代传值 使用react传值的时候你还在通过父组件&#xff0c;收兄弟一的值给兄弟二吗&#xff0c;跨代传值还在一层层的去穿props吗&#xff0c;如果还在这么做&#xff0c;我觉得看了这个案例&#xff0c;应该会对你所帮助。 如果用过vue的应该…

使用js在网页上记录鼠标划圈的小程序

JavaScript中通常分为两种类型转换&#xff0c;“隐式强制类型转换”&#xff08;implicit coercion&#xff09;和“显式强制类型转换”&#xff08;explicit coercion&#xff09;。 下面所有代码的源码可以在此处查看。 一、强制转换为字符串&#xff08;ToString&#xff0…

【云扩RPA】LoginConsole

登录云扩控制台 此节将延续上节课程&#xff0c;在等待手机登录特征元素出现后&#xff0c;执行流程决策的True分支 准备工作 打开上节课程的流程文件已经注册云扩控制台账号&#xff0c;可通过手机号登录 定义变量并存入手机号和密码 点击设计面板下的 变量标签&#xff…

[macOS] keychain的跳坑之旅!git拉取的权限问题

故事背景&#xff0c;svn与git各有长处&#xff0c;不过git大势所趋吧&#xff0c;那就搞搞。git的服务端&#xff0c;是基于phabricator搭建的&#xff0c;关于它的资料自行google就好了。其实之前运维已经搭好了phabricator了&#xff0c;也给过我叫做test的账号去试过了&…