javascript - 在 React 中构建一个大型多选而不是真的很慢

标签 javascript performance reactjs multi-select

我正在构建的应用程序需要相当多的多选。它在用户界面中工作,因为我正在使用 this library这让人们可以搜索选项,但我无法在合理的时间内在 React 中呈现它。

Link to 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 个项目,不会花那么长时间。这些不是我要找的答案。

编辑:看起来 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)上执行与您的 react 代码相同,大约 5000 毫秒。

如果我使用 Microsoft Edge,时间从 5000 毫秒变为 231 毫秒( react )和 12 毫秒(DOM 操作)。这里 Chrome DOM 很慢(与 Edge 相比),并且选项元素最终必须呈现给 DOM。更新可能会更快。

我已经编写了一些代码来做同样的事情,但不是 <select> field 。这是一个无序列表,列表项具有点击处理程序。性能大约提高 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

关于javascript - 在 React 中构建一个大型多选而不是真的很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34729642/

相关文章:

javascript - Spring MVC 如何将带有数据的 View 结果发送到ajax代码?

javascript - 在 HTML 中绑定(bind) JS 金字塔

javascript - 如何使用 Promise 查看 setTimeout 中错误的完整堆栈跟踪

javascript - 只获取 FileStack JSON.stringify 的 url 值?

java - 实现由二维数组中的值支持的模型类的最快、最简洁/正确的方法是什么?

javascript - 当我上传文件后尝试读取事件目标时,事件目标返回为空

javascript - 在 Typescript 中声明类型时,类型 'never[]' 的参数不可分配给类型 'never' 的参数

javascript - 数组方法的复杂性

java - 如何调用按钮事件监听器。甚至没有被点击?

javascript - 在 react 应用程序中位置更改之前解码网址