在React中构建一个大型多选,而不会非常缓慢
Building a large multiselect in React without it being really slow
我正在构建的应用程序需要大量的多选。它在用户界面中工作,因为我使用这个库,它可以让人们搜索选项,但我无法在React中在合理的时间内渲染它。
链接到JSFiddle。
我制作了一个更简单的版本,显示了相同的问题。
它包含一些设置代码,可以创建一个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)
}
);
最后,组件本身,它只对list
中的所有选项进行简单的多选,并默认检查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>
)
}
});
在我的计算机上运行此fiddle会产生一个警报,在1000毫秒内显示以渲染此组件。如果我将默认列表的限定符从x%1
更改为x%50
,那么有10个选定项目,只需要76毫秒。
起初,我认为瓶颈只是构建500个option
元素,但似乎速度减慢实际上是由于使用了大量默认值。
所以我想我的问题是:
- 有人知道如何获得相同的结果以更快地渲染吗
- 当谈到React性能时,我是否缺少一些见解
- 为什么添加默认值会增加这么多开销
谢谢。
请注意,我意识到React在JSFiddle中的运行速度会变慢,在生产中我应该使用React的生产版本,和,如果我不把我的列表列为500项,就不会花那么长时间。这些不是我想要的答案。
EDIT:看起来React可能会一次一个地将每个option
标记为selected
,从而导致500个重发。这也许可以解释发生了什么——这是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)
jsfiddle
它在我的机器(Chrome 47,Windows 10)上执行与您的反应代码相同的代码,大约5000毫秒。
如果我使用Microsoft Edge,时间从5000ms变为231ms(react)和12ms(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>
jsfiddle
- 对iPad上的点击事件反应缓慢
- Ajax请求文档就绪会导致jquery加载缓慢
- Xpath运行缓慢的查询
- 如何使用javascript onmouseover缓慢放大图像
- 通过javascript操作图像,非常简单
- 具有大型数据集的组件仅在 IE11/Edge 上运行缓慢
- 非常简单的XMLHttpRequest不起作用
- Bootstrap在页面加载缓慢时会立即显示隐藏的模式对话框
- hiddenfield的值显示得非常缓慢
- 聚合物元素加载非常缓慢
- 使用JSON的iPad,平板电脑和手机的图像加载非常缓慢
- Gulp babel es2015 转换非常缓慢
- 在React中构建一个大型多选,而不会非常缓慢
- 更改跨度文本非常缓慢
- 由于外部库,Webpack构建非常缓慢
- 在IE11中添加大量元素非常缓慢
- 在ios+chrome上输入字段是缓慢的/非常慢
- 如何调试一个网站模板,这是非常缓慢的(客户端)
- 大型同位素画廊非常缓慢
- 在JavsScript中删除关联数组中的元素——>非常缓慢