一、虚拟DOM中key的作用

key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM,随后Vue会对新虚拟DOM与旧虚拟DOM的差异进行比较。

二、如何选择key

最好使用每条数据的唯一标识作为key,用一个简单的例子说明:

1.用index作为key时

点击按钮在列表最前方添加赵六用户

  <ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}
<input type="text">
</li>
<br>
<button @click="Add">在最前方添加一个用户</button>
</ul>
 data () {
return {
persons: [
{id: '01', name: '张三'},
{id: '02', name: '李四'},
{id: '03', name: '王五'}
]
}
},
methods: {
Add () {
let p = {id: '04', name: '赵六'}
this.persons.unshift(p)
}
}

点击以后,页面如下图

然而,如果在我点击按钮前,在输入框中输入一些内容

点击按钮后就会变成



很明显,这并不是我们理想中想要呈现的效果。

2.用id作为key时

<ul>
<li v-for="p of persons" :key="p.id">
{{p.name}}
<input type="text">
</li>
<br>
<button @click="Add">在最前方添加一个用户</button>
</ul>

在输入框中输入与之前相同的内容,点击按钮后这次的页面则变成了下图



很明显,这次就对了!

三、原因分析

为什么用id和index作为key出来的效果天差地别呢,首先来分析一下key的作用原理。

用index作为key时:

首先会根据初始数据生成虚拟DOM,然后将虚拟DOM转为真实DOM,在加入新数据以后,再根据新数据生成新的虚拟DOM,此时Vue并不会再重新将新虚拟DOM直接转为真实DOM,而是进行一个虚拟DOM的对比算法。如下:

首先在新的虚拟DOM中按照顺序取出第一项,然后根据标识“key=0”在旧的虚拟DOM中寻找拥有一样“key=0”的节点,然后开始挨个对比。

第一个节点为文本节点,Vue发现一个为张三一个为赵六,不一致,于是将新的文本节点赵六转为真实DOM

然后来到第二个标签节点input,需要注意的是,我们对文本框的输入是在真实DOM中操作的,但在虚拟DOM中两边的标签节点input是一样的,所以这时候Vue不会将它重新转成真实DOM,而是直接复用左边的。

以此类推,key等于1和等于2时,文本节点重新转为真实DOM,标签节点复用。

当来到key等于3这一项时,发现左边并没有key是等于3的一项,所以这个时候,Vue直接将右边key等于3这一项直接转为真实DOM。

用id作为key时:

首先也是按照顺序取出第一项,然后根据标识“key=04”在左边寻找拥有同样key的一项,发现没有,于是直接转为真实DOM。

然后按顺序取出第二项,根据标识“key=01”,在左边寻找也是“key=01”的一项,挨个对比文本节点和标签节点,发现两个节点都完全一样,所以直接复用之前的真实DOM。

以此类推,李四和王五都是直接复用左边的真实DOM。

四、总结

  1. 用index作为key可能会引发的问题:若对数据进行逆序添加、逆序删除等破坏顺序的操作时,会产生没有必要的真实DOM更新,此时界面效果没有问题,但效率太低。
  2. 在开发中如何选择key:最好使用每条数据的唯一标识作为key,比如id、身份证号、手机号等,如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。

v-for中key的作用与原理的更多相关文章

  1. vue中:key 和react 中key={} 的作用,以及ref的特性?

    vue中:key 和react 中key={} 为了给 vue 或者react 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性 一句话概括就是 ...

  2. vue中key的作用 v-for里警告 v-if的复用

    vue总是会复用页面上已经存在的dom,区别的方法是加上key就可以,还设有v-for时候的警告也是如此key的作用是区别这条跟那条的.<body> <div id="ap ...

  3. vue中key的作用

    1.v-if中用key管理可复用的元素  Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染.这么做,除了使 Vue 变得非常快之外,还有一些有用的好处.例如,如果你允许用户在不同的 ...

  4. @Transacitonal注解不生效之spring中expose-proxy的作用与原理

    几年前记得整理过,@Transacitonal注解的方法被另外一个方法调用的时候,事务是不生效的. 如果大量代码已经这么写了,这个时候抽取出去不现实,怎么办呢? 答案就是在<aop:aspect ...

  5. Vue2.0 v-for 中 :key 的作用

  6. Vue学习之--------列表渲染、v-for中key的原理、列表过滤的实现(2022/7/13)

    文章目录 1.基本列表 1.1 基本知识 1.2 代码实例 1.3 测试效果 2.key的原理 2.1基本知识 2.2 代码实例 2.3 测试效果 2.4 原理图解 3.列表过滤 3.1 代码实例 3 ...

  7. 【react】---react中key值的作用

    一.React中key值得作用 react中的key属性,它是一个特殊的属性,它是出现不是给开发者用的,而是给React自己使用,有了key属性后,就可以与组件建立了一种对应关系,简单说,react利 ...

  8. react中key的使用

    面试题: 1). react/vue中的key的作用/内部原理 2). 为什么列表的key尽量不要用index 虚拟DOM的key的作用? 1). 简单的说: key是虚拟DOM对象的标识, 在更新显 ...

  9. 图解vue中 v-for 的 :key 的作用,虚拟dom Diff算法

    其实不只是vue,react中在执行列表渲染时也会要求给每个组件添加上key这个属性. 要解释key的作用,不得不先介绍一下虚拟DOM的Diff算法了. 我们知道,vue和react都实现了一套虚拟D ...

随机推荐

  1. NC202475 树上子链

    题目链接 题目 题目描述 给定一棵树 T ,树 T 上每个点都有一个权值. 定义一颗树的子链的大小为:这个子链上所有结点的权值和 . 请在树 T 中找出一条最大的子链并输出. 输入描述 第一行输入一个 ...

  2. 刷题记录:Codeforces Round #731 (Div. 3)

    Codeforces Round #731 (Div. 3) 20210803.网址:https://codeforces.com/contest/1547. 感觉这次犯的低级错误有亿点多-- A 一 ...

  3. C#基础_枚举

    一.在学习枚举之前,首先来听听枚举的优点. 1.枚举能够使代码更加清晰,它允许使用描述性的名称表示整数值. 2.枚举使代码更易于维护,有助于确保给变量指定合法的.期望的值. 3.枚举使代码更易输入. ...

  4. python使用pickle序列化对象读取输出二进制文件

    import pickle class tick: name = '牛牛牛' age = 10 samp = [1,2,3,'aaa',[12,3],tick()] with open('te.xxx ...

  5. Helm安装ingress-nginx-4.1.4

    Application version 1.2.1 Chart version 4.1.4 获取chart包 helm fetch ingress-nginx/ingress-nginx --vers ...

  6. Dubbo-Adaptive实现原理

    前言 前面我们已经分析Dubbo SPI相关的源码,看过的小伙伴相信已经知晓整个加载过程,我们也留下两个问题,今天我们先来处理下其中关于注解Adaptive的原理. 什么是@Adaptive 对应于A ...

  7. multiprocessing 让子进程忽略信号,手动关闭子进程

    起因 同事想要写一个代码,主进程中监听SIGINT.SIGTERM信号退出,并关闭启动的子进程,代码类似这样 import signal import sys import time from mul ...

  8. 第十四章 二进制部署k8s集群的平滑升级

    1.软件包下载 去github上下载较新的Kubernetes软件包https://github.com/ 2.升级说明 升级包括master节点升级和node节点的升级,本章升级至v1.15.12: ...

  9. vscode主题开发

    vscode主题开发教程 https://blog.csdn.net/Suwanqing_su/article/details/105945290 个人配置结果 主题代码 到Vscode放插件的目录中 ...

  10. LFS(Linux From Scratch)构建过程全记录(三):下载所需的软件包

    写在前面 本文将记录构建LFS的过程中,下载软件包的全过程 准备下载的路径 注意请确保$LFS已经设置完毕 我们需要创建一个文件夹,地址为$LFS/sources,用于保存对应的源码 输入的指令如下: ...