2016-12-30 852 views
3

我已經經歷了很多StackOverflow的答案。我在這裏也經歷了List文檔,react-virtualized/List。但是,我仍然無法理解如何在react-virtualized列表中動態設置行高度。如何計算rowHeight道具函數的高度?如何在react-virtualized List中設置動態行高?

我可以打電話給我的功能,如rowHeight={({ index }) => this.computeRowHeight({ index })}。但函數如何計算行高?

以下是供參考的代碼。

import React, { Component } from 'react'; 
import ReactDOM from 'react-dom'; 
import { AutoSizer, InfiniteLoader, List } from 'react-virtualized'; 
import _ from 'lodash'; 

class InfiniteList extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     list: props.list, 
     loading: false 
    }; 
    } 
    componentDidMount() { 
    fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      this.setState({ 
      list: _.concat(this.state.list, _.map(data, 'body')), 
      loading: false 
      }); 
     }); 
     }); 
    } 
    isRowLoaded({ index }) { 
    return !!this.state.list[index]; 
    } 

    loadMoreRows({ startIndex, stopIndex }) { 
    if (this.state.loading) { 
     return; 
    } 
    this.setState({ 
     loading: true 
    }); 
    return fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      // Simulate delay 
      setTimeout(() => { 
      this.setState({ 
       list: _.concat(this.state.list, _.map(data, 'body')), 
       loading: false 
      }); 
      }, 3000); 
     }); 
     }); 
    } 

    rowRenderer({ key, index, isScrolling, isVisible, style }) { 
    if (isVisible) { 
     return (
     <div key={key}> 
      <div style={style}>#{this.state.list[index]}.</div> 
     </div> 
    ); 
    } 
    } 

    render() { 
    return (
     <div> 
     <InfiniteLoader 
      isRowLoaded={({ index }) => this.isRowLoaded({ index })} 
      loadMoreRows={({ startIndex, stopIndex }) => this.loadMoreRows({ startIndex, stopIndex })} 
      rowCount={this.state.list.length} 
     > 
      {({ onRowsRendered, registerChild }) => (
      <AutoSizer disableHeight> 
       {({ width }) => (
       <List 
        onRowsRendered={onRowsRendered} 
        ref={registerChild} 
        width={width} 
        height={320} 
        rowCount={this.state.list.length} 
        rowHeight={40} 
        rowRenderer={({ key, index, isScrolling, isVisible, style }) => this.rowRenderer({ key, index, isScrolling, isVisible, style })} 
       /> 
      )} 
      </AutoSizer> 
     )} 
     </InfiniteLoader> 
     {this.state.loading && <p>Loading...</p>} 
     </div> 
    ); 
    } 
} 

const list = []; 

ReactDOM.render(
    <InfiniteList list={list} />, 
    document.querySelector('#root') 
); 

更新

動態高度現在與CellMeasurer下面的代碼工作。但是,不幸的是this.loadMoreRows()函數在InfiniteLoader中沒有被調用。沒有CellMeasurer也不起作用。我不確定我在下面的代碼中做了什麼錯誤。

import React, { Component } from 'react'; 
import { AutoSizer, CellMeasurer, InfiniteLoader, List } from 'react-virtualized'; 
import _ from 'lodash'; 

class InfiniteList extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     list: props.list, 
     loading: false 
    }; 
    } 
    componentDidMount() { 
    fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      this.setState({ 
      list: _.concat(this.state.list, _.map(data, 'body')), 
      loading: false 
      }); 
     }); 
     }); 
    } 
    isRowLoaded({ index }) { 
    return !!this.state.list[index]; 
    } 

    loadMoreRows({ startIndex, stopIndex }) { 
    if (this.state.loading) { 
     return; 
    } 
    this.setState({ 
     loading: true 
    }); 
    return fetch('http://jsonplaceholder.typicode.com/comments') 
     .then((response) => { 
     response.json().then((data) => { 
      // Simulate delay 
      setTimeout(() => { 
      this.setState({ 
       list: _.concat(this.state.list, _.map(data, 'body')), 
       loading: false 
      }); 
      }, 3000); 
     }); 
     }); 
    } 

    rowRenderer({ key, index, isScrolling, isVisible, style }) { 
    if (isVisible) { 
     return (
     <div key={key} style={style}>#{index} {this.state.list[index]}.</div> 
    ); 
    } 
    } 
    cellRenderer({ columnIndex, key, rowIndex, style }) { 
    return (
     <div 
     key={key} 
     style={style} 
     > 
     <div>#{rowIndex} {this.state.list[rowIndex]}.</div> 
     </div> 
    ); 
    } 
    render() { 
    return (
     <div> 
     <InfiniteLoader 
      isRowLoaded={isRowLoaded => this.isRowLoaded(isRowLoaded)} 
      loadMoreRows={loadMoreRows => this.loadMoreRows(loadMoreRows)} 
      rowCount={this.state.list.length} 
     > 
      {({ onRowsRendered, registerChild }) => (
      <AutoSizer disableHeight> 
       {({ width }) => (
       <CellMeasurer 
        cellRenderer={cellRenderer => this.cellRenderer(cellRenderer)} 
        columnCount={1} 
        rowCount={this.state.list.length} 
       > 
        {({ getRowHeight }) => (
        <List 
         onRowsRendered={onRowsRendered} 
         ref={registerChild} 
         width={width} 
         height={400} 
         rowCount={this.state.list.length} 
         rowHeight={getRowHeight} 
         rowRenderer={rowRenderer => this.rowRenderer(rowRenderer)} 
        /> 
       )} 
       </CellMeasurer> 
      )} 
      </AutoSizer> 
     )} 
     </InfiniteLoader> 
     {this.state.loading && <p>Loading...</p>} 
     </div> 
    ); 
    } 
} 

const list = []; 

ReactDOM.render(
    <InfiniteList list={list} />, 
    document.querySelector('#root') 
); 

任何幫助將不勝感激。謝謝!

回答

0

您需要自己編寫computeRowHeight來確定行的高度。在某些情況下,根據該行的索引和屬性,您可能會知道該行的高度。例如,如果您的行可能是不同的組件,如果您知道某個行將是組件A的高度爲40,另一行將是組件B的高度爲60,則可以檢查這些支持並返回正確的高度。

如果你不知道高度,那麼你將不得不真的看DOM中的元素,並找出它的高度。如果它不存在於DOM中,則需要首先返回最佳猜測,然後在渲染後調用recomputeRowHeights,然後檢查DOM。

+1

添加到德魯的答案,如果你不知道任何關於你的內容的大小,你可能想要使用像CellMeasurer這樣的另一個react-virtualized組件。我也聽說過人們使用react-measure與react-virtualized結果很好。 – brianvaughn

+0

@brianvaughn謝謝!以前我無法通過CellMeasurer獲得動態高度。但是,我再次嘗試了一下,現在它正在工作(儘管有時很少的行重疊)。但是,不幸的是我的'this.loadMoreRows()'函數沒有在InfiniteLoader中調用。我認爲它在CellMeasurer之前也沒有工作。所以它與CellMeasurer無關。我不確定我在這裏做錯了什麼。謝謝你的時間! – krishnaxv

+0

我明白了這一點。我必須在'InfiniteLoader'中的'rowCount'中給出任意高數字,而不是'rowCount = {this.state.list.length}'。 – krishnaxv