2016-01-11 13 views
3

我正在構建的應用程序需要一個相當大的多選。它在用戶界面中工作,因爲我使用的是this library,它允許用戶搜索選項,但我無法在合理的時間內將它渲染到React中。在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> 
    ) 
    } 
}); 

茹在我的電腦上找到這個小提琴產生一個警報,顯示超過1000毫秒呈現此組件。如果我將缺省列表的限定符從x%1更改爲x%50,那麼有10個選定項目,只需要76毫秒。起初,我認爲瓶頸只是構建了500 option元素,但看起來放緩實際上來自使用大量的默認值。

所以我想我的問題是:

  • 有誰知道一種方式來獲得相同的結果來呈現更快?
  • 我是否在React性能方面缺少一些見解?
  • 爲什麼要添加默認添加這麼多開銷?

謝謝。

並請注意,我意識到反應會運行中的jsfiddle慢,而且在生產,我應該使用反應,的量產版和,如果我沒有讓我的名單500個項目長時間不會這麼長時間。這些不是我正在尋找的答案。

編輯:它看起來像React可能會標記每個optionselected一次一個,導致500次重投。這可能會解釋發生了什麼 - 這是React中的一個錯誤嗎?我看到'強制同步佈局是一個可能的性能瓶頸'。 Chrome開發者工具中的警告。

回答

3

你所看到的是第一個渲染緩慢的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

它作爲你的反應代碼我的機器上(鉻47,視窗10),約5000毫秒執行相同。

如果我使用Microsoft Edge,時間從5000ms到231ms(反應)和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

+1

是的,如果你的時間表配置文件,您可以看到,這將創建一噸的重新計算樣式。即使沒有React也會發生這種情況 –

+0

我要正確地標記這個答案,因爲它只是與Chrome的渲染有關,而不是React。儘管我已經用Chrome填充了這個bug,因爲在大約十分之一或更短的時間內,Firefox,Safari和IE都運行同樣的東西。 – fnsjdnfksjdb