Key 到底有什么用?
面试必问,这篇文章给你讲明白
先说结论:Key 就是 React 用来识别列表元素身份的"身份证"。
Key 的作用
React 的 Diff 算法靠 Key 来判断元素是"新建了"、"删除了"还是"移动了":
- Key 不存在 → 新建
- Key 消失了 → 删除
- Key 还在但位置变了 → 移动
如果没有 Key,React 就没办法知道元素到底啥情况,只能傻傻地逐个对比更新——性能差,还容易出 bug。
为什么不能用 index?
静态列表可以用 index,如果你的列表永远不增不减不排序,那用 index 完全没问题。
但如果列表会变化,问题就来了:
头部插入数据
// 原来的列表
[A, B, C][ // index: 0, 1, 2
// 在头部插入 New
(New, A, B, C)
]; // index: 0, 1, 2, 3
React 发现:
- index=0 的组件还在(其实是 A 被复用成了 New)→ 内容改成 New
- index=1 的组件还在(其实是 B 被复用成了 A)→ 内容改成 A
- index=2 的组件还在(其实是 C 被复用成了 B)→ 内容改成 B
- C 被判断为新增
结果:所有组件都被更新了一遍,性能炸裂。
状态错乱
如果列表项里有非受控组件(比如输入框):
items.map((item, index) => <input key={index} defaultValue={item.name} />);
当你在中间插入一项时,输入框的内容会"跑错位置"——因为 React 复用了组件实例,状态也一起带过去了。
正确用法
用 ID(推荐)
items.map((item) => <Item key={item.id} {...item} />);
来自数据库的唯一 ID,永远不变,最靠谱。
生成的 Hash
如果数据没有 ID,可以根据内容生成一个唯一标识(前提是内容本身不重复):
items.map((item) => <Item key={generateHash(item)} {...item} />);
万不得己才用 index
// 纯展示的静态列表,可以用 index
items.map((item, index) => <div key={index}>{item.name}</div>);
总结
| 场景 | Key 怎么选 |
|---|
| 数据库数据 | 用 item.id |
| 动态生成 | 用 Hash |
| 静态列表 | 可以用 index |
记住:列表会变就用 ID,别偷懒用 index,不然后面有你好受的。