小红书面试:v-for循环,为什么不建议使用index作为key?

开发 前端
假如,我们使用 index 作为 key,同时使用 unshift 方法为数组添加了一个新的元素,那么所有的 index 都会发生变化,从而导致:isSameVNodeType 返回 false,即:所有的 dom 全部重新渲染 从而影响性能。

Hello,大家好,我是 Sunday。

最近有个同学在小红书三面的时候遇到了一个面试题:“v-for循环,为什么不建议使用index作为key?”

按说这个问题并不复杂,所以该同学直接回答:“使用 index 作为 key 可能会导致渲染性能问题,特别是数据源使用了 unshift 将数据添加到头部时,会导致 index 被重新规划,从而导致重新渲染。”

然后面试官继续追问:“为什么 index 变化了就会导致 dom 重新渲染?它的渲染机制是什么?”

额... 吃了没有看过源码的亏,导致这个问题并没有回答出来(但愿该同学这次小红书面试可以顺利通过,毕竟都到技术三面了)。

所以,咱们今天就针对这个面试题来说一下。

v-for 循环的渲染时机

在 Vue 的渲染中,有两个比较重要的渲染时机:渲染、更新。

  • 渲染:指的是 DOM 的首次渲染。首次的渲染性能的消耗是固定的。
  • 更新:指的是 数据变化后影响到的视图变化,所谓的性能问题,主要就集中在这里。

我们以这段代码为例,以下代码表示的就是一段 更新 的逻辑:

<template>
 <div>
  <ul>
   <li v-for="(item, index) in list" :key="index">{{ item }}</li>
  </ul>
  <button @click="change">change</button>
 </div>
</template>

<script setup>
const list = ref([1, 2, 3])

const change = () => {
 list.value = [3, 2, 1]
}
</script>

如果我们把 [1, 2, 3] 作为一组 dom,把 [3, 2, 1] 作为另外一组 dom,那么 dom 由 [1, 2, 3] 变成 [3, 2, 1] 的过程就是 DOM 更新。

key 在渲染中的作用

同时,我们需要注意:针对于 v-for 的 dom 更新,一定是:两组 dom 对比发生的变化。

而在 vue 中,一旦两组 dom 对比更新,那么就会触发 diff 算法 的逻辑,而在 diff 中有这样一段 vue 的源代码 isSameVNodeType:

图片图片

这段代码是用来判断 两个 DOM 是否相等的。

它的判断条件有两个:

  1. type:表示当前 dom 的类型,比如:li、div、p 等不同标签名
  2. key:v-for 循环中绑定的 key 值

那么由此我们就可以知道:在 vue 中,通过 type + key 两个属性来判断 dom 是否相等。

如果条件满足(isSameVNodeType 返回 true),那么就不会重新渲染 dom,从而可以 提升性能

index 为什么会影响性能?

根据上面的内容,我们可以知道:在 type 不变的前提下,key 就决定了 dom 是否要重新渲染。

假如,我们使用 index 作为 key,同时使用 unshift 方法为数组添加了一个新的元素,那么所有的 index 都会发生变化,从而导致:isSameVNodeType 返回 false,即:所有的 dom 全部重新渲染 从而影响性能

责任编辑:武晓燕 来源: 程序员Sunday
相关推荐

2024-03-11 11:02:03

Date类JavaAPI

2023-09-21 10:50:23

MySQL数据库

2020-12-15 10:00:31

MySQL数据库text

2020-11-17 09:01:09

MySQLDelete数据

2021-11-15 06:56:45

MyBatis开发项目

2021-08-04 17:20:30

阿里巴巴AsyncJava

2020-12-24 18:46:11

Java序列化编程语言

2021-10-13 14:06:46

MySQLUtf8符号

2019-01-29 10:30:32

阿里巴巴Java字符串

2019-02-27 09:00:13

阿里巴巴for循环Java

2020-12-22 06:04:13

Python定时代码

2020-04-01 17:50:02

Python编程语言

2024-02-28 07:37:53

JavaExecutors工具

2020-06-23 14:09:49

枚举JDK场景

2022-02-06 10:58:37

Redis主从模式

2020-08-31 11:20:53

MySQLuuidid

2021-01-26 21:00:24

SSL证书网络安全加密

2021-07-01 16:10:22

equals字符串Java

2021-06-08 08:14:52

Vuev-for循环

2021-03-10 09:40:50

Linux命令文件
点赞
收藏

51CTO技术栈公众号