问题分析
- 相信大多数童鞋在使用React的时候,特别是遍历渲染元素的时候,都见过下面这个 Warning
index.js:1446 Warning: Each child in a list should have a unique "key" prop.
- 所以我都会习惯性的给 item 指定一个
key
, 而有的时候为了方便我们会直接把list 的索引指定成key
,但是这样所并不被推荐,那这是为什么呢?
刨根问底
我们知道react的执行步骤一般是:
-
用state和jsx模板生成虚拟DOM,然后用虚拟DOM生成真实的 DOM,当我们state发生变化时,render函数执行,生成新的 虚拟DOM,然后比较新旧虚拟DOM的区别,找到区别,然后直接操作DOM,改变有区别的内容,这样比传统的操作DOM,极大的提升了性能。
-
而虚拟DOM的核心就是——
React
的diff算法
,要搞清楚这个问题我们首先要来看看 diff算法
我们从上图可以看出React 在更新虚拟DOM的时候是逐层往下的,也就是说第一层div时就有出现区别,那么对比结束,直接更新真实DOM中对应的当前节点,以此类推。
Solve the problem
- 好! 现在我们可以来看看 这个
key
了,假设我们在state中有一个列表[A,B,C],在遍历渲染时用索引作为key,那么就是这样的.
A 0
B 1
C 2
复制代码
如果我们执行一个操作,点击删除数组中的a, 我们的列表就是[b,c],在遍历渲染时仍然会用索引作为key,结果如下:
如图 ,我们如果不用索引为key , 程序能快速的对比出差异,反之也能对出差异,但是必须对比整个虚拟DOM, 这样,程序仍然能正常执行,只不过大大消耗了新旧虚拟DOM的对比的性能,并可能导致组件状态问题。
- 所以,把索引设置为key值,可以吗?
可以,但是不推荐这样做,因为会大大消耗虚拟DOM的性能