当前位置: 首页 > news >正文

为什么不用 index 做 key?

“在 Vue 中,我们在使用 v-for 渲染列表的时候,为什么要绑定一个 key?能不能用 indexkey?”

在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。

虚拟DOM

我们知道,Vue 不可以直接操作 DOM 结构,而是通过数据驱动、指令等机制来间接操作 DOM 结构。当我们修改模版中的数据时,Vue 会触发重新渲染过程,调用render函数,它会返回一个 虚拟 DOM 树,它描述了整个组件模版的结构。

什么是虚拟DOM呢?虚拟DOM是一个对象,没想到吧...我们来看看Vue是如何将template模板里面的东西交给浏览器来渲染的

举个栗子🌰:

<template><ul class="list"><li v-for="item in list" :key="item.index" class="item">{{ item }}</li></ul>
</template><script setup>
import { ref } from 'vue';
const list = ref(['html', 'css', 'js'])
</script>

Vue 在渲染这个列表时,就会调用render函数,它会返回一个类似下面这个虚拟 DOM 树。

let VDom = {tagName: 'ul',props: {class: 'list'},chilren: [{tagName: 'li',props: {class: 'item'},chilren: ['html']},{tagName: 'li',props: {class: 'item'},chilren: ['css']},{tagName: 'li',props: {class: 'item'},chilren: ['js']}]
}

虚拟 DOM 的每个节点对应于真实 DOM 树中的一个节点。

当我们修改数据时,Vue 又会触发重新渲染的过程。

const list = ref(['html', 'css', 'vue']) //修改列表第三项'js'->'vue'

Vue 又会生成一个新的虚拟DOM树:

let VDom = {tagName: 'ul',props: {class: 'list'},chilren: [{tagName: 'li',props: {class: 'item'},chilren: ['html']},{tagName: 'li',props: {class: 'item'},chilren: ['css']},{tagName: 'li',props: {class: 'item'},chilren: ['vue']}]
}

注意观察,这里最后一个节点的子节点为'vue',发生了数据变化,Vue内部又会返回一个新的虚拟 DOM。那么 Vue 是如何将这个变化响应给页面的呢?

摆在面前的有两条路

要么重新渲染这个新的虚拟 DOM ,要么只新旧虚拟 DOM 之间改变的地方。

显而易见,只渲染修改了的地方是不是会更节省性能。

巧了,尤雨溪也是这样想的,于是便有了“ Diff 算法 ”。

Diff 算法

Vue 将新生成的新虚拟 DOM 与上一次渲染时生成的旧虚拟 DOM 进行比较,对比出是哪个虚拟节点更改了,找出这个虚拟节点,并只更新这个虚拟节点所对应的真实节点,而不用更新其他数据没发生改变的节点。

我自己总结了一下Diff算法的过程,由于代码过多,就不在此展示了:

  1. 新旧虚拟DOM对比的时候,Diff 算法比较只会在同层级进行,不会跨层级比较。
  2. 首先比较两个节点的类型,如果类型不同,则废弃旧节点并用新节点替代。
  3. 对于相同类型的节点,进一步比较它们的属性。记录属性差异,以便生成相应的补丁。
  4. 如果两个节点相同,继续递归比较它们的子节点,直到遍历完整个树。
  5. 如果节点有唯一标识,可以通过这些标识来快速定位相同标识的节点。
  6. 如果节点的相同,只是顺序变化,不会执行不必要的操作。

面试官:为什么不用 index 做 key?

平常v-for循环渲染的时候,为什么不建议用 index 作为循环项的 key 呢?

举个栗子🌰:

<div id="app"><ul><li v-for="item in list" :key="item.index">{{item}}</li></ul><button @click="add">添加</button>
</div>
<script>const { createApp, ref } = VuecreateApp({setup() {const list = ref(['html', 'css', 'js']);const add=()=> {list.value.unshift('阳阳羊');}return {list,add}}}).mount('#app')
</script>

我们发现添加操作导致的整个列表的重新渲染,按道理来说,Diff 算法会复用后面的三项,因为它们只是位置发生了变化,内容并没有改变。但是我们回过头来发现,我们在前面添加了一项,导致后面三项的 index 变化,从而导致 key 值发生变化。Diff 算法失效了?

那我们可以怎么解决呢?其实我们只要使用一个独一无二的值来当做key就行了

<div id="app"><ul><li v-for="item in list" :key="item.id">{{item.name}}</li></ul><button @click="add">添加</button>
</div>
<script>const { createApp, ref } = VuecreateApp({setup() {const list = ref([{ name: "html", id: 1 }, { name: "css", id: 2 }, { name: "js", id: 3 }, ]);const add=()=> {list.value.unshift({ name: '阳阳羊', id: 4 });}return {list,add}}}).mount('#app')
</script>

这样,key就是永远不变的,更新前后都是一样的,并且又由于节点的内容本来就没变,所以 Diff 算法完美生效,只需将新节点添加到真实 DOM 就行了。

如果后端没有返回 唯一 id ,唯一标识都可以的

最后

看到这里,希望你已经对Diff 算法有了初步的了解,想要深入了解,可以自行查看Diff 源码。总的来说,Diff 算法是一项关键的技术,为构建响应式和高效的用户界面提供了基础。最后,祝你面试顺利,学习进步!

相关文章:

为什么不用 index 做 key?

“在 Vue 中&#xff0c;我们在使用 v-for 渲染列表的时候&#xff0c;为什么要绑定一个 key&#xff1f;能不能用 index 做 key&#xff1f;” 在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。 虚拟DOM 我们知道&#xff0c;Vue 不可以直接操作 DOM 结构&am…...

Linux虚拟机安装Redis

官网下载压缩包&#xff1a;官网链接&#xff0c;然后将对应的tar.gz压缩包放入虚拟机下的/opt目录下。由于redis是C语言开发的&#xff0c;因此需要安装gcc编译器来编译代码&#xff0c;我们下载的压缩包里面是源代码&#xff0c;需要编译。通过yum install gcc指令下载C语言的…...

网络安全: Kali Linux 进行 SSH 渗透与防御

目录 一、实验 1.环境 2.nmap扫描目标主机 3.Kali Linux 进行 SSH 渗透 3.Kali Linux 进行 SSH 防御 二、问题 1.SSH有哪些安全配置 一、实验 1.环境 &#xff08;1&#xff09;主机 表1 主机 系统版本IP备注Kali Linux2022.4 192.168.204.154&#xff08;动态&…...

近年来文本检测相关工作梳理

引言 场景文本检测任务&#xff0c;一直以来是OCR整个任务中最为重要的一环。虽然有一些相关工作是端对端OCR工作的&#xff0c;但是从工业界来看&#xff0c;相关落地应用较为困难。因此&#xff0c;两阶段的OCR方案一直是优先考虑的。 在两阶段中&#xff08;文本检测文本识…...

文件系统事件监听

文件系统事件和网络IO事件一样&#xff0c;也可以通过epoll或者IOCP 事件管理器统一调度&#xff0c;当所监控的文件或文件夹发生了增删改的事件时&#xff0c;就会触发事件回调&#xff0c;进行事件处理。很常见的应用&#xff0c;如配置文件立即生效功能&#xff0c;就可以通…...

探秘HTTPS:如何通过SSL/TLS保证网络通信安全

目录 引言 详解HTTPS加密实现机制 SSL/TLS工作原理 结论 引言 随着网络安全威胁的日益增加&#xff0c;HTTPS通过SSL&#xff08;Secure Sockets Layer&#xff09;和TLS&#xff08;Transport Layer Security&#xff09;协议提供的加密技术变得至关重要。这些技术保证了用…...

Java算法之动态规划

Java算法之动态规划 前言 ​ 最近这一段时间一直在刷算法题&#xff0c;基本上一有时间就会做一两道&#xff0c;这两天做了几道动态规划的问题&#xff0c;动态规划之前一直是我比较头疼的一个问题&#xff0c;感觉好复杂&#xff0c;一遇到这样的问题就想跳过&#xff0c;昨…...

C++从零开始的打怪升级之路(day47)

这是关于一个普通双非本科大一学生的C的学习记录贴 在此前&#xff0c;我学了一点点C语言还有简单的数据结构&#xff0c;如果有小伙伴想和我一起学习的&#xff0c;可以私信我交流分享学习资料 那么开启正题 今天分享的是关于set和map的知识点 1.关联式容器 在前面&#…...

香橙派AIpro开发板开箱测评

2023年12月&#xff0c;香橙派联合华为发布了基于昇腾的Orange Pi AIpro开发板&#xff0c;提供8/20TOPS澎湃算力&#xff0c;能覆盖生态开发板者的主流应用场景&#xff0c;让用户实践各种创新场景&#xff0c;并为其提供配套的软硬件。香橙派AIpro开发板一经发布便吸引了众多…...

ISP基础概述

原文来自ISP 和摄像头基本知识 本文主要介绍ISP&#xff0c;以供读者能够理解该技术的定义、原理、应用。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;计算机杂记 &#x1f380;CSDN主页 发狂的小花 &#x1f3…...

C++第一弹---C++入门(上)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 【C详解】 C入门 1、C关键字(C98) 2、命名空间 2.1、命名空间定义 2.2、命名空间使用 3、C输入&输出 4、缺省参数 4.1、缺省参数概念 4.2、缺省参…...

VScode格式化快捷键

vscode格式化代码快捷键 如何使用快捷键格式化代码。使用Java的格式去设置&#xff0c;发现不起作用。 在这里记录一下&#xff1a; 在Windows中&#xff0c;vscode格式化代码快捷键是“ShiftAltF”&#xff1b; 在Mac中&#xff0c;vscode格式化代码快捷键是“ShiftOption…...

HCIP---IS-IS协议

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一.IS-IS协议概述 IS-IS是一种基于链路状态的内部网关协议&#xff08;IGP&#xff09;&#xff0c;它使用最短路径优先算法&#xff08;SPF或Dijkstra&#xff09;进行路由计算。这种协议在自治…...

突破编程_C++_设计模式(组合模式)

1 组合模式的基本概念 C中的组合模式是一种对象结构型模式&#xff0c;它将多个对象组合成树形结构&#xff0c;以表示具有整体-部分关系的层次结构。在这个模式中&#xff0c;对单个对象&#xff08;叶子对象&#xff09;与组合对象&#xff08;容器对象&#xff09;的使用具…...

010Editor汉化版+下载+注册码+模板bug

项目场景&#xff1a; 这天我想使用我的不知名的一个破解版本的010Edit来查看一个EXE程序&#xff0c;并想使用模板功能&#xff0c;但是发现没有该模板还无法下载最新模板 问题描述 010Edit联网后需要注册码&#xff1a; 010 Editor 激活码生成器 使用方法 参照教程使用0…...

js【详解】BOM

浏览器对象模型 &#xff08;Browser obiect Mode 简称 BOM&#xff09; 浏览器对象即 window&#xff0c;调用window对象的属性和方法时&#xff0c;可以省略window window 常用的属性 Navigator 常用于获取浏览器的信息 navigator.userAgent;火狐浏览器范例&#xff1a; “…...

Leetcode 3077. Maximum Strength of K Disjoint Subarrays

Leetcode 3077. Maximum Strength of K Disjoint Subarrays 1. 解题思路 1. 朴素思路2. 算法优化 2. 代码实现 题目链接&#xff1a;3077. Maximum Strength of K Disjoint Subarrays 1. 解题思路 这道题很惭愧没有搞定&#xff0c;思路上出现了差错&#xff0c;导致一直没能…...

【JetsonNano】onnxruntime-gpu 环境编译和安装,支持 Python 和 C++ 开发

1. 设备 2. 环境 sudo apt-get install protobuf-compiler libprotoc-devexport PATH/usr/local/cuda/bin:${PATH} export CUDA_PATH/usr/local/cuda export cuDNN_PATH/usr/lib/aarch64-linux-gnu export CMAKE_ARGS"-DONNX_CUSTOM_PROTOC_EXECUTABLE/usr/bin/protoc&qu…...

知名比特币质押协议项目Babylon确认参加Hack.Summit()2024区块链开发者大会

Babylon项目已确认将派遣其项目代表出席2024年在香港数码港举办的Hack.Summit()2024区块链开发者大会。作为比特币生态的领军项目&#xff0c;Babylon积极参与全球区块链领域的交流与合作&#xff0c;此次出席大会将为其提供一个展示项目进展、交流技术与创新思路的重要平台。B…...

如何学习、上手点云算法(三):用VsCode、Visual Studio来debug基于PCL、Open3D的代码

写在前面 本文内容 以PCL 1.14.0&#xff0c;Open3D0.14.1为例&#xff0c;对基于PCL、Open3D开发的代码进行源码debug&#xff1b; 如何学习、上手点云算法系列&#xff1a; 如何学习、上手点云算法(一)&#xff1a;点云基础 如何学习、上手点云算法(二)&#xff1a;点云处理相…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...