2017-06-13 25 views
0

我有一個反應組件,它顯示網格模式中的項目的一維列表。每個項目都有相同的寬度和高度,它們位於三列內。可以有很多這樣的東西,所以我決定使用Masonry組件進行反應 - 虛擬化,這個組件似乎是爲了這個用例而寫的。它的效果很好,但有一點需要注意:如果物品改變高度,我不能讓砌體注意。我如何告訴砌體組件它的單元已經改變了它們的高度?

這裏的一個減小的例子:

constructor(props) { 
    [...] 
    this.cellMeasurerCache = new CellMeasurerCache({ 
     defaultHeight: this.state.height, 
     fixedWidth: true, 
    }); 

    this.cellPositioner = createMasonryCellPositioner({ 
     cellMeasurerCache: this.cellMeasurerCache, 
     columnCount: 3, 
     columnWidth: 250, 
     spacer: 20, 
    }); 
} 

[...] 

cellRenderer({ index, key, parent, style }) { 
    return (
     <CellMeasurer 
      cache={this.cellMeasurerCache} 
      index={index} 
      key={key} 
      parent={parent} 
     > 
      <div style={style}> 
       [...] 
      </div> 
     </CellMeasurer> 
    ); 
} 

resetMasonry() { 
    this.cellMeasurerCache.clearAll(); 

    this.cellPositioner.reset({ 
     cache: this.cellMeasurerCache, 
     columnCount: 3, 
     columnWidth: 250, 
     spacer: 20, 
    }); 

    this.masonryRef.recomputeCellPositions(); 
} 

render() { 
    return (
     <AutoSizer> 
      {({ height, width }) => 
       <Masonry 
        cellCount={this.state.list.length} 
        cellMeasurerCache={this.cellMeasurerCache} 
        cellPositioner={this.cellPositioner} 
        cellRenderer={this.cellRenderer} 
        height={height} 
        ref={this.setMasonryRef} 
        width={width} 
       /> 
      } 
     </AutoSizer> 
    ); 
} 

resetMasonry當組件的高度的狀態已經改變時被調用。我已經從幾個stackoverflow答案和其他資源中檢索了當前的代碼,甚至查看了源代碼,但沒有任何結果。我注意到,我沒有告訴cellMeasurerCache或其他關於高度變化的事情,所以我真的不應該期待它的工作,但似乎沒有辦法在那裏獲取信息,甚至沒有實例化新的CellMeasurerCache。順便說一下,如果我更改cellPositioner.reset中的columnWidth,那麼Masonry組件會相應地進行更新,果不其然。

有沒有人知道我錯過了什麼讓它工作的高度變化?謝謝!

回答

2

如果您的Masonry單元的尺寸發生變化,您需要清除CellMeasurerCache中的緩存尺寸,然後確保cellPositioner也知道新的尺寸。例如:

// Clear cached measurements since sizes have changed: 
cellMeasurerCache.clearAll() 

// Let your component know it needs to re-render 
this.setState({...},() => { 
    // Assuming you're using the default createCellPositioner() 
    // Let it know of any values that may have changed: 
    cellPositioner.reset({ 
    columnCount, 
    columnWidth, 
    spacer 
    }) 

    // Tell Masonry to discard any cached position data: 
    masonryRef.clearCellPositions() 
}) 

您只需通過改變列寬看到Masonry成分與上RV site改變柱高度的演示。該演示的源代碼也可用in the GitHub repo

從你所描述的,但我不會建議使用Masonry。我真的只是建議以類似的方式使用List來我在這個例子中是怎麼做:http://plnkr.co/edit/zjCwNeRZ7XtmFp1PDBsc?p=preview

關鍵位是計算每個動態基於可用寬度行項目的數量,然後你給List的調整爲rowCount

const itemsPerRow = Math.floor(width/ITEM_SIZE); 
    const rowCount = Math.ceil(ITEMS_COUNT/itemsPerRow); 
+0

非常感謝您的回答!使用'List'是一個正確的選擇(我知道如何使用它,因爲我在另一個顯示全長項目列表的組件中這樣做)。我用例中的列數永遠不會改變,所以很容易適應。 現在我想知道「砌體」組件的用途是什麼,如果不是這樣的話?另外,事實證明我錯過的是使用'clearCellPositions'而不是'recomputeCellPositions'。這樣做會導致組件注意到高度的變化,但它只更新了其中一些項目,而不是全部...... –

+0

無論如何,使用簡單的'List'工作得很好,再次感謝! –

+0

'砌體'旨在用於Pinterest佈局。實際上,我在與其中一位工程師討論過之後,專門爲Pinterest創建了組件。 (不知道他們是否選擇使用它。)由於項目的高度都相同,因此'List'更易於使用。 :) – brianvaughn

相關問題