key 必须用 unique id(如 item.id)而非 index,因为 index 随增删排序动态变化,会导致 vue diff 算法误判节点身份,引发输入框内容错位、动画异常、子组件状态丢失;index 仅可用于展示或样式控制。

在 Vue 列表渲染中,index 和 unique ID 各司其职:index 用于逻辑判断或展示(如序号、首项样式),而 unique ID(如 item.id)必须作为 :key 的值,这是保障渲染正确性与性能的核心前提。
为什么 key 一定要用 unique ID,不能用 index
Vue 的 diff 算法依赖 key 来追踪节点身份。index 是动态的——插入、删除或排序时会变化,导致:
- 输入框内容错位(比如在第2项输入后删掉第1项,原第2项变成第1项,但 Vue 复用了旧 DOM,内容“粘”在错误位置)
- 过渡动画异常(节点身份识别混乱,动画触发错乱)
- 子组件状态丢失(如带内部
v-model的表单组件重新挂载)
如何正确同时使用 index 和 unique ID
语法上直接解构即可:v-for="(item, index) in list",然后分开使用:
-
:key="item.id"—— 唯一、稳定、业务语义明确 -
{{ index + 1 }}—— 展示从 1 开始的序号(index 本身从 0 起) -
:class="{ 'active': index === 0 }"—— 给首项加特殊样式 -
@click="handleClick(item, index)"—— 需要位置信息时传入事件处理器
没有后端 ID 怎么办?别硬凑 index
若数据确实无自然唯一字段(如纯字符串数组 ['a','b','c']),可选更稳妥的替代方案:
- 前端生成唯一 key:初始化时调用
crypto.randomUUID()并存入每项(适合本地临时数据) - 用哈希拼接:如
createHash(item.title + item.timestamp),确保结构稳定且不重复 - 避免用
JSON.stringify(item)—— 对象属性顺序稍有差异就会产生不同 key,风险高
render 函数里也要遵守 same rule
在函数式组件或 setup() 中使用 h() 渲染列表时,key 必须显式写在 props 中:
- ✅ 正确:
h('li', { key: item.id }, ...) - ❌ 错误:
h('li', { key: index }, ...)—— render 函数不会警告,但问题更隐蔽 - 注意 key 类型统一:不要混用字符串 ID 和数字 index,否则
'1'和1被视为两个 key
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











