在react中,如果要渲染一个列表,我们会用map()函数将数组循环处理然后渲染到DOM,在处理循环时,“key” 是一个你需要包含的特殊字符串属性。
很多时候,我们会使用当前列表的索引为key,但这样做真的好吗?
要讨论这个问题,我们要从react的原理说起,我们react的执行步骤一般是:用state和jsx模板生成虚拟DOM,然后用虚拟DOM生成真实的 DOM,当我们state发生变化时,render函数执行,生成新的 虚拟DOM,然后比较新旧虚拟DOM的区别,找到区别,然后直接操作DOM,改变有区别的内容,这样比传统的操作DOM,极大的提升了性能。
再说虚拟DOM,虚拟DOM其实就是一个JS对象(['div',{class:'app'},'item']),虚拟DOM核心之一是diff算法,diff算法的核心之一是同层对比,如图:
如果在第一层div时就有出现区别,那么对比结束,直接更新真实DOM中对应的当前节点,以此类推。。。
再说说key,假设我们在state中有一个列表[a,b,c],在遍历渲染时用索引作为key,那么就是这样:
a 0
b 1
c 2
如果我们执行一个操作,点击删除数组中的a, 我们的列表就是[b,c],在遍历渲染时仍然会用索引作为key,结果如下:
b 0
c 1
如图 ,我们如果不用索引为key , 程序能快速的对比出差异,反之也能对出差异,但是必须对比整个虚拟DOM,
这样,程序仍然能正常执行,只不过大大消耗了新旧虚拟DOM的对比的性能,并可能导致组件状态问题。