Vue列表渲染的坑:为什么不能用index当key?血泪教训总结!

前言

大家好,我是小杨,一个写了6年前端的老司机。今天要聊一个Vue里看似简单但90%新手都会踩的坑------用index当key。这玩意表面人畜无害,实际暗藏杀机,轻则数据错乱,重则性能爆炸。不信?往下看我的翻车实录!


一、index当key的灾难现场

上周我写了个代办事项列表,代码长这样:

html 复制代码
<!-- 天真无邪的写法 -->
<ul>
  <li v-for="(todo, index) in todos" :key="index">
    {{ 我 }}的任务:{{ todo.text }}
  </li>
</ul>

看起来没问题对吧?直到我加了删除功能...

翻车过程:

  1. 假设有三个任务:["买菜", "写代码", "摸鱼"]

  2. 删除第二个"写代码"后

  3. Vue根据index认为:

    • 旧节点0(买菜)→ 新节点0(买菜) ✔
    • 旧节点1(写代码)→ 新节点1(摸鱼) ❌
    • 旧节点2(摸鱼)→ 被删除

结果:本该显示["买菜", "摸鱼"],却可能触发组件异常复用,导致:

  • 输入框状态错乱
  • 动画效果错位
  • 控制台疯狂警告

二、为什么index是万恶之源?

1. 数组变异操作直接暴击

  • 当发生删除/插入时,所有后续元素的index全变了
  • 但Vue觉得:"咦,key=1的节点还在嘛(其实内容已经物是人非)"

2. 性能杀手

看这个例子:

js 复制代码
// 初始数据
const todos = [
  { id: 1, text: "买菜" },
  { id: 2, text: "写代码" }
]

// 头部插入新任务
todos.unshift({ id: 3, text: "开会" })

用index当key时:

  • 所有
  • 的key都变了(0→1, 1→2)
  • 导致全部DOM重新渲染(其实只需要在头部加一个DOM)

用id当key时:

  • 只有新加的
  • 会创建
  • 其他DOM原地复用

三、正确姿势指南

✅ 方案1:用数据唯一标识

html 复制代码
<li v-for="todo in todos" :key="todo.id">
  {{ todo.text }}
</li>

✅ 方案2:实在没id怎么办?

js 复制代码
// 方法1:前端生成唯一ID
todos.map(todo => ({
  ...todo,
  _id: Math.random().toString(36).slice(2)
}))

// 方法2:用内容哈希(仅限内容不会重复)
:key="hash(todo.text)"

❌ 这些情况千万别用index!

  • 列表有增删操作
  • 列表项包含表单元素
  • 需要过渡动画
  • 列表项是有状态组件

四、血的教训

去年我们项目有个诡异bug:

  1. 表格允许拖拽排序
  2. 每行有个计数器组件
  3. 拖拽后计数器的值会随机交换

排查三天发现 :有人写了:key="index"。改成:key="row.id"后,世界和平了。


五、总结

  • 🚫 index当key ≈ 埋地雷
  • 唯一id当key = 稳如老狗
  • 💡 没有id就创造id(但别用index!)

下次写v-for时,记得摸摸头顶------哦不,记得检查key!你的头发会感谢你。

⭐ 写在最后

请大家不吝赐教,在下方评论或者私信我,十分感谢🙏🙏🙏.

✅ 认为我某个部分的设计过于繁琐,有更加简单或者更高逼格的封装方式

✅ 认为我部分代码过于老旧,可以提供新的API或最新语法

✅ 对于文章中部分内容不理解

✅ 解答我文章中一些疑问

✅ 认为某些交互,功能需要优化,发现BUG

✅ 想要添加新功能,对于整体的设计,外观有更好的建议

✅ 一起探讨技术加qq交流群:906392632

最后感谢各位的耐心观看,既然都到这了,点个 👍赞再走吧!

相关推荐
90后的晨仔1 分钟前
在 macOS 上轻松获取 GIF 图片总时长:多种实用方法详解
前端
技术钱2 分钟前
vue3前端解析excel文件
前端·vue.js·excel
mapbar_front27 分钟前
顺利通过试用期:避开三大陷阱,掌握三个关键点
前端·面试
韩立学长37 分钟前
【开题答辩实录分享】以《智慧校园勤工俭学信息管理系统的设计与实现》为例进行答辩实录分享
vue.js·spring boot·微信小程序
掘金安东尼43 分钟前
Transformers.js:让大模型跑进浏览器
开发语言·javascript·ecmascript
why技术1 小时前
1K+Star的开源项目能给一个在校大学生带来什么?
前端·人工智能·后端
@PHARAOH1 小时前
HOW - localstorage 超时管理方案
前端·javascript·vue.js
im_AMBER1 小时前
React 05
开发语言·前端·javascript·笔记·学习·react.js·前端框架
showker1 小时前
ecstore等产品开启缓存-后台及前台不能登录原因-setcookie+session问题
java·linux·前端
DokiDoki之父1 小时前
前端速通—Vue_简介 & 第一个Vue程序 & el:挂载点 & data:数据对象 & Vue指令
javascript·vue.js·ecmascript