我正在构建的应用程序需要相当多的选择.它在用户界面中工作,因为我使用的是this library,它使人们可以搜索选项,但是我无法在合理的时间内在React中渲染它.
我制作了一个更简单的版本来显示相同的问题.
它包含一些设置代码,该代码创建了500个项目的列表.它还列出了默认情况下应选择的项目.现在,我将其设置为x%1,因此默认情况下每个选项都处于启用状态,因为这似乎是瓶颈.我还启动了startTime变量只是为了跟踪事物.
var list = [];
var defaultList = [];
for (var x = 0; x < 500; x += 1) {
list.push(x);
if (x%1 === 0) {
defaultList.push(x)
}
}
var startTime=new Date().getTime();
然后,使用ReactDom.render()将其传递到组件中,该组件具有一个回调,用于提醒渲染后经过了多少毫秒:
ReactDOM.render(
<Hello
list={list}
defaultList={defaultList}
/>,
document.getElementById('container'),
()=>{
alert(new Date().getTime() - startTime)
}
);
最后,组件本身仅对列表中的所有选项进行简单的多选,并默认检查defaultList中的所有选项:
var Hello = React.createClass({
render: function() {
return (
<select defaultValue={this.props.defaultList} multiple>
{this.props.list.map(item => {
return (<option value={item} key={item}>{item}</option>)
})}
</select>
)
}
});
在我的计算机上运行此小提琴会产生一个警报,该警报显示要渲染此组件的时间超过1000毫秒.如果我将默认列表的限定词从x%1更改为xP,那么有10个选定项,则只需76毫秒.
最初,我认为瓶颈只是建立500个option元素,但似乎减速实际上是由于使用大量默认值造成的.
所以我想我的问题是:
>是否有人知道获得相同结果以更快渲染的方法?
>关于React性能,我是否缺少一些见识?
>为什么添加默认值会增加这么多开销?
谢谢.
而且请注意,我知道React在JSFiddle中的运行速度会变慢,并且在生产环境中,我应该使用React的生产版本,并且如果我不将清单中的500个项目排得很长,也就不会花那么长时间.这些不是我要的答案.
编辑:看起来React可能一次将每个选项都标记为选中的选项,从而导致500个rerender.这也许可以解释发生了什么-这是React中的错误吗?我看到“强制同步布局是可能的性能瓶颈”. Chrome开发者工具中的警告.
解决方法:
您所看到的是DOM的第一个渲染缓慢.采取以下代码:
let html = '<select multiple>'
for (var x = 0; x < 500; x += 1) {
html += `<option value=${x} selected>${x}</option>`
}
html += '</select>'
var startTime=new Date().getTime();
document.getElementById('container').innerHTML = html;
alert(new Date().getTime() - startTime)
它的性能与您在我的计算机(Chrome 47,Windows 10)上的反应代码相同,约为5000毫秒.
如果使用Microsoft Edge,则时间从5000毫秒变为231毫秒(反应时间)和12毫秒(DOM操作).在这里,Chrome DOM较慢(与Edge相比),并且必须将选项元素最终呈现为DOM.更新可能更快.
我做了一些相同的代码,但不是< select>领域.这是一个无序列表,列表项具有单击处理程序.性能提高了约10倍(Chrome约为500ms,Edge约为300ms).
class Select extends React.Component {
constructor (props) {
super(props)
this.state = {}
this.state.selected = props.selected
}
handleClick () {
this.setState({selected: !this.state.selected})
}
render () {
const val = this.props.value
const selected = this.state.selected
return (
<li onClick={this.handleClick.bind(this)} className={selected ? 'selected' : ''}>
{val}
</li>
)
}
}
const Hello = ({list, defaultList}) =>
<ul>
{list.map(item =>
<Select key={item} value={item} selected={defaultList.indexOf(item) !== -1}/>)}
</ul>