2017-01-12 53 views
0

如果我可以使用React Virtualized的收集組件來解決我的問題,我有點困惑。我將嘗試描述我在做什麼:React虛擬化:收集具有相同固定高度但寬度不同的單元格

我在頁面上使用React虛擬化來顯示兩個列表/項目集合。我已經完成了其具有具有相同的寬度和高度項目第一個集合:

Collection where cells have same height & width

首先收集是非常簡單的,易於實現。 現在我正在處理包含不同尺寸圖像的第二個集合。我希望單元具有相同的高度,但寬度不同(取決於圖像尺寸當然)。問題是,行可能並不總是有相同數量的細胞:

Collection where cells have same height but different width

這是可能實現與虛擬化作出反應?如果是這樣,我如何確定「cellSizeAndPositionGetter」中的位置?

+0

一個短nswer:你不能。我能想到的解決方法是將實際行中的所有單元格分開,因此第1行將顯示前三個圖像,而第2行將顯示下一個四個單元格。然後你會自己虛擬化這些行,而不是單個單元。這是一般虛擬化列表的「設計上」限制(「列表」,而不是「網格」)。 –

+0

我同意Sergiu所說的。要多添加一點,你展示的頂級集合應該是一個「Grid」而不是「Component」。 'Grid'使用起來更加高效和簡單。你顯示的第二個可能是一個'List',但計算行數會有點棘手。 – brianvaughn

+0

@brianvaughn我猜你的意思是'集合'而不是'組件'?無論如何,我明白你們倆都在說什麼。我想我會嘗試第一次收集「Grid」。對於第二個集合,我最終使用[CassetteRocks/react-infinite-scroller](https://github.com/CassetteRocks/react-infinite-scroller)。當我有一些空閒時間時,我會嘗試再次使用React Virtualized來實現第二個集合。因爲我真的很喜歡回購! :)謝謝你的投入。 – Jooooooooohn

回答

1

我最近使用react-virtualizedList來顯示固定高度,可變寬度的圖像行的行,它的工作很好。

我的ListrowRenderer使用圖像卡元素的行數組。也就是說,作爲JSX的反應組件陣列。

請參閱我的最終功能cardsRows,瞭解如何根據元素寬度和屏幕寬度構建行。

下面是它的外觀:

List rows layout

希望這有助於!

我的代碼的某些代碼段:

import {AutoSizer, List} from 'react-virtualized'; 

...

updateDimensions() { 
    this.setState({ 
     screenWidth: window.innerWidth, 
    }); 
} 

componentDidMount() { 
    window.addEventListener("resize", this.updateDimensions); 
} 


componentDidUpdate(prevProps, prevState) { 
    const props = this.props; 
    const state = this.state; 

    if (JSON.stringify(props.imageDocs) !== JSON.stringify(prevProps.imageDocs) || state.screenWidth !== prevState.screenWidth) 
     this.setState({ 
      cardsRows: cardsRows(props, state.screenWidth), 
     }); 
} 


rowRenderer({key, index, style, isScrolling}) { 
    if (!this.state.cardsRows.length) 
     return ''; 
    return (
     <div id={index} title={this.state.cardsRows[index].length} key={key} style={style}> 
      {this.state.cardsRows[index]} 
     </div> 
    ); 
} 

...

render() { 
    return (
      <div style={styles.subMain}> 
       <AutoSizer> 
        {({height, width}) => (<List height={height} 
               rowCount={this.state.cardsRows.length} 
               rowHeight={164} 
               rowRenderer={this.rowRenderer} 
               width={width} 
               overscanRowCount={2} 
         /> 
        )} 
       </AutoSizer> 
      </div> 
    ); 
} 

...

const cardsRows = (props, screenWidth) => { 

    const rows = []; 
    let rowCards = []; 
    let rowWidth = 0; 
    const distanceBetweenCards = 15; 

    for (const imageDoc of props.imageDocs) { 
     const imageWidth = getWidth(imageDoc); 

     if (rowWidth + distanceBetweenCards * 2 + imageWidth <= screenWidth) { 
      rowCards.push(cardElement(imageDoc)); 
      rowWidth += distanceBetweenCards + imageWidth; 
     } 
     else { 
      rows.push(rowCards); 
      rowCards = []; 
      rowWidth = distanceBetweenCards; 
     } 
    } 
    if (rowCards.length) { 
     rows.push(rowCards); 
    } 
    return rows; 
}; 


const styles = { 
    subMain: { 
     position: 'absolute', 
     display: 'block', 
     top: 0, 
     right: 0, 
     left: 0, 
     bottom: 0, 
    } 
}; 
相關問題