龙空技术网

使用Perf工具研究React Key对渲染的影响

爱音乐的程序员小新人 105

前言:

眼前看官们对“react的key值为什么不用数组下标”都比较关切,姐妹们都想要剖析一些“react的key值为什么不用数组下标”的相关资讯。那么小编同时在网络上汇集了一些对于“react的key值为什么不用数组下标””的相关资讯,希望姐妹们能喜欢,各位老铁们快快来学习一下吧!

使用React的开发版本时常会遇到这样的情况:

渲染列表时, 不为数组的每一项设置key, 则控制台会警告

Warning: Each child in an array or iterator should have a unique “key” prop.

Check the render method of Constructor.

See for more information.

我常看到有的代码为了消除警告, 把数组的下标(index)作为key, 那么这倒底是不是一种好的做法呢, 本文将一探究竟.

准备工作

在页面引入react-with-addons.js, 可以去bootcdn随便找一个.

进行本文的实验时, 我使用的是0.13.1版本. 后面我又当前最新版本15.3.1重新试过, 实验结果是一致的, 只是输出的信息在描述上有些差异, 我就没重新截图了.

背景知识

1.列表初始化

列表一开始长这个样子

2.列表项信息

列表项DOM结构如下

1

2

3

4

5

<div>

<span className={'checkbox ' + (data.isDefault ? 'active' : '')} ref="checkbox"/>

<span>{data.id}</span>

<span className="delete" ref="delete">删除</span>

</div>

每一个列表项都可以做两个操作:

点击checkbox, 设置该项为默认列表项.点击删除, 删除该项

以上操作都触发列表刷新, 即重新获取列表数据;

返回的数据结构为数组, 数组的第一项是默认项;

每一个列表项的id都是唯一的

3.Reconciliation

When a component’s props or state change, React decides whether an actual DOM update is necessary by constructing a new virtual DOM and comparing it to the old one. Only in the case they are not equal, will React reconcile the DOM, applying as few mutations as possible

每当组件的props或state改变时, React会重新创建一个virtual DOM, 与上一个作对比, 如果发现两个virtual DOM不完全相同, 则React就会做reconcile(姑且翻译成”较正”吧), 把有差异的地方更新到真实的DOM上(这当然是建立在shouldComponentUpdate方法返回true的前提下, 那又是另一个话题了).

4.Perf工具的基本使用

打开浏览器的控制台:

执行操作前, 调用 React.addons.Perf.start()执行操作后, 调用 React.addons.Perf.stop()第2步之后, 调用 React.addons.Perf.printDOM() 相看React对DOM的操作情况

第3步, 如果用更高版本的React, 可能会让你使用React.addons.Perf.printOperations

更多方法请看官方文档

进行实验

改变默认项

点击第二个checkbox, 设置id为39的列表项为默认项, 观察列表重新渲染的结果

1.使用id作为key

渲染结果与后台返回数据一致

使用Perf工具得到的结果:

2.使用index作为key

渲染结果与后台数据不完全一致, 表现为checkbox选中的情况不对

使用Perf工具得到的结果:

删除列表项

删除列表的第一个项目, 看看React是怎么渲染的

1.使用id作为key

调整列表顺序, 让id为37的列表项在前面, 然后点击删除(则列表只剩下id为39的列表项)

为方便说明, 表示如下:

1

[{key: '37', text: '37'}, {key: '39', text: '39'}] => [{key: '39', text: '39'}]

使用Perf工具得到的结果:

可以看出React直接把key为37的项目删除掉了

2.使用index作为key

新建一个列表项, id为46(id不受我控制, 我也想40, 囧…)

调整列表顺序, 让id为39的列表项在前面, 然后点击删除

为方便说明, 表示如下:

1

[{key: '0', text: '39'}, {key: '1', text: '46'}] => [{key: '0', text: '46'}]

使用Perf工具得到的结果:

上图表明, React先把key为0的项目, 再删除key为1的项目.

换句话说, 如果这个列表有10条数据, 则React会先更新前面9条数据, 再删除第10条数据.

结论

使用React渲染列表时, 把数组的下标作为key是不正确的, 它能做的, 仅仅是消除警告而已, 对渲染的毫无帮助.

React的key应该是稳定的, 唯一的(只要在列表项中唯一就行). 把数组的下标作为key的缺点在于没有满足稳定性要求

推荐把id或uuid等字段作为React的key, 减少React对DOM操作

另: 相同的key, 只有第一个节点会被渲染

Encountered two children with the same key, '.0:$1'. Child keys must be unique; when two children share a key, only the first child will be used.

标签: #react的key值为什么不用数组下标 #react用index作为key