为什么 Vue 中不要用 index 作为 key

news/2024/11/13 18:03:48

```javascript
Vue 中的 key 是用来做什么的?为什么不推荐使用 index 作为 key
<ul>
  <li>1</li>
  <li>2</li>
</ul>
{
  tag: 'ul',
  children: [
    { tag: 'li', children: [ { vnode: { text: '1' }}]  },
    { tag: 'li', children: [ { vnode: { text: '2' }}]  },
  ]
}
假设更新以后,我们把子节点的顺序调换了一下
{
  tag: 'ul',
  children: [
+   { tag: 'li', children: [ { vnode: { text: '2' }}]  },
+   { tag: 'li', children: [ { vnode: { text: '1' }}]  },
  ]
}
这里的 children 部分是我们本文 diff 算法要讲的重点(敲黑板)。

响应式数据更新后,触发了 渲染 Watcher  的回调函数 vm._update(vm._render())去驱动视图更新
_render() 其实生成的就是 vnode,而 vm._update 就会带着新的 vnode 去走触发 __patch__ 过程
直接进入 ul 这个 vnode 的 patch 过程。

为什么不要以index作为key?
 <div id="app">
      <ul>
        <item
          :key="index"
          v-for="(num, index) in nums"
          :num="num"
          :class="`item${num}`"
        ></item>
      </ul>
      <button @click="change">改变</button>
    </div>
    <script src="./vue.js"></script>
    <script>
      var vm = new Vue({
        name: "parent",
        el: "#app",
        data: {
          nums: [1, 2, 3]
        },
        methods: {
          change() {
            this.nums.reverse();
          }
        },
        components: {
          item: {
            props: ["num"],
            template: `
                    <div>
                       {{num}}
                    </div>
                `,
            name: "child"
          }
        }
      });
    </script>
    简单的列表组件,渲染出来 1 2 3 三个数字。我们先以 index 作为key,来跟踪一下它的更新。
   item 列表节点的更新,在首次渲染的时候,我们的虚拟节点列表 oldChildren 粗略表示是这样的
  [
  {
    tag: "item",
    key: 0,
    props: {
      num: 1
    }
  },
  {
    tag: "item",
    key: 1,
    props: {
      num: 2
    }
  },
  {
    tag: "item",
    key: 2,
    props: {
      num: 3
    }
  }
];  
在我们点击按钮的时候,会对数组做 reverse 的操作。那么我们此时生成的 newChildren 列表是这样的:
[
  {
    tag: "item",
    key: 0,
    props: {
+     num: 3
    }
  },
  {
    tag: "item",
    key: 1,
    props: {
+     num: 2
    }
  },
  {
    tag: "item",
    key: 2,
    props: {
+     num: 1
    }
  }
];
**为什么不要用随机数作为key**
<item
  :key="Math.random()"
  v-for="(num, index) in nums"
  :num="num"
  :class="`item${num}`"
/>
**首先 oldVnode 是这样的**

[
  {
    tag: "item",
    key: 0.6330715699108844,
    props: {
      num: 1
    }
  },
  {
    tag: "item",
    key: 0.25104533240710514,
    props: {
      num: 2
    }
  },
  {
    tag: "item",
    key: 0.4114769152411637,
    props: {
      num: 3
    }
  }
];
更新·之后·
[
  {
    tag: "item",
+   key: 0.11046018699748683,
    props: {
+     num: 3
    }
  },
  {
    tag: "item",
+   key: 0.8549799545696619,
    props: {
+     num: 2
    }
  },
  {
    tag: "item",
+   key: 0.18674467938937478,
    props: {
+     num: 1
    }
  }
];
diff 子节点的首尾对比如果都没有命中,就会进入 key 的详细对比过程,简单来说,就是利用旧节点的 key -> index 的关系建立一个 map 映射表,然后用新节点的 key 去匹配,如果没找到的话,就会调用 createElm 方法 重新建立 一个新节点
diff 子节点的首尾对比如果都没有命中,就会进入 key 的详细对比过程,简单来说,就是利用旧节点的 key -> index 的关系建立一个 map 映射表,然后用新节点的 key 去匹配,如果没找到的话,就会调用 createElm 方法 重新建立 一个新节点
用组件唯一的 id(一般由后端返回)作为它的 key,实在没有的情况下,可以在获取到列表的时候通过某种规则为它们创建一个 key,并保证这个 key 在组件整个生命周期中都保持稳定。
别用 index 作为 key,和没写基本上没区别,因为不管你数组的顺序怎么颠倒,index 都是 0, 1, 2 这样排列,导致 Vue 会复用错误的旧子节点,做很多额外的工作。
千万别用随机数作为 key,不然旧节点会被全部删掉,新节点重新创建,你的老板会被你气死。

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

相关文章

Eclipse个最实用的快捷键

一个Eclipse骨灰级开发人员总结了他觉得最实用但又不太为人所知的快捷键组合。通过这些组合能够更加easy的浏览源码&#xff0c;使得总体的开发效率和质量得到提升。 1. ctrlshiftr&#xff1a;打开资源 这可能是全部快捷键组合中最省时间的了。这组快捷键能够让你打开你的工作…

字符函数和内存函数(二)

目录 一、strtok函数 二、strerror函数 三、memcpy函数 3.1memcpy函数的认识 3.2memcpy函数的模拟实现 四、memmove函数 4.1memmove函数的认识 4.2memmove函数的模拟实现 五、memcmp函数 5.1memcmp函数的认识 5.2memcmp函数的模拟实现 六、memset函数 七、字符分类函…

面试考点导图

在这里插入代码片

爬虫练习之数据整理——基于Pandas

上一篇->爬虫练习之数据清洗——基于Pandas 本次以51Job上在东莞地区爬取的以Java为关键词的招聘数据 包括salary company time job_name address字段目的 本次数据整理的小目标是将薪资数据拿出来单独处理为统一的格式, 以便后续的数据统计分析和可视化操作 思路 先来看看数…

cookie sessionStorage localStorage区别

cookie sessionStorage localStorage区别 cookie数据始终在同源的http请求中携带(即使不需要)&#xff0c;即cookie在浏览器和服务器间来回传递 cookie数据还有路径&#xff08;path&#xff09;的概念&#xff0c;可以限制。cookie只属于某个路径下 存储大小限制也不同&#…

RNAseq 流程

https://github.com/twbattaglia/RNAseq-workflow

.net object对象操作json数组,并且获取object对象中数组所对应的值

using Newtonsoft.Json; string jsonstr "[{\"id\":1,\"name\":\"张三\"},{\"id\":2,\"name\":\"李四\"}]"; List<object> sg new List<object>(); var json JsonConvert.DeserializeAn…

工作中遇到的问题用第三方如何解决input默认的背景色

javascri 在input中 假如要去掉placeholder的默认背景色 则-webkit-box-shadow: 0 0 0 1000px white inset; }