2

現在、 のようなアイテムのリストがあり<ul><li/><li/>...</ul>、それぞれが でスタイル設定されていdisplay: inline-blockます。アイテムの高さや幅は固定ではありませんが、おそらく固定することもできます。各アイテムにはサムネイル画像と、場合によってはテキストが含まれています。

ウィンドウの幅が変化すると、リストは応答してラップされ、水平スクロールバーはありません。たとえば、リストは 3 つの項目で始まり、すべてがウィンドウ内の行に水平に収まる場合があります。

| 1 2 3     |

次に、いくつかの項目が追加され、項目が 2 行目に折り返され始めます。

| 1 2 3 4 5 |
| 6 7 8     |

次に、ウィンドウの幅が変更されると、アイテムが再ラップされます。

| 1 2 3 4 5 6 7 |
| 8             |

何千ものアイテムがある場合、パフォーマンスは確実に低下する可能性があるため、リストを仮想化する方法があるかどうかを確認したかったのです。ドキュメントを読んだところ、これが現在 React Virtualized ライブラリでサポートされているようには見えませんが、確認したかったのです。コンポーネントはCollection近いように見えますが、ウィンドウのサイズが変更されると、幅や高さが動的に変更されるとは思われません。

この種のアイテムのラッピングが可能である場合、実装例はありますか?

4

1 に答える 1

4

ドキュメントを読んだところ、これが現在 React Virtualized ライブラリでサポートされているようには見えません。

ドキュメントのどの部分があなたにこのような印象を与えたのか知りたいです. あなたのユースケースは、react-virtualized が十分に処理できるように思えます。:)

コンポーネントはCollection近いようです

Collection他の何かを意図しています。おそらく、私が最近行った会議の講演からのこれらのスライドは、それを少し明確にすることができます. 基本的にCollectionは、非線形データ (ガント チャート、Pinterest レイアウトなど) 用です。より柔軟ですが、パフォーマンスが犠牲になります。あなたのユースケースはList. :)

更新された回答

とを使用ListAutoSizerてこれを実現できます。利用可能な幅とアイテムの高さを使用して行数を計算するだけです。複雑すぎません。:)

以下は Plunker の例で、ソースは次のとおりです。

const { AutoSizer, List } = ReactVirtualized

const ITEMS_COUNT = 100
const ITEM_SIZE = 100

// Render your list
ReactDOM.render(
  <AutoSizer>
    {({ height, width }) => {
      const itemsPerRow = Math.floor(width / ITEM_SIZE);
      const rowCount = Math.ceil(ITEMS_COUNT / itemsPerRow);

      return (
        <List
          className='List'
          width={width}
          height={height}
          rowCount={rowCount}
          rowHeight={ITEM_SIZE}
          rowRenderer={
            ({ index, key, style }) => {
              const items = [];
              const convertedIndex = index * itemsPerRow;

              for (let i = convertedIndex; i < convertedIndex + itemsPerRow; i++) {
                items.push(
                  <div
                    className='Item'
                    key={i}
                  >
                    Item {i}
                  </div>
                )
              }

              return (
                <div
                  className='Row'
                  key={key}
                  style={style}
                >
                  {items}
                </div>
              )
            }
          }
        />
      )
    }}
  </AutoSizer>,
  document.getElementById('example')
)

最初の回答

多かれ少なかれ、私がすることは次のとおりです。

export default class Example extends Component {
  static propTypes = {
    list: PropTypes.instanceOf(Immutable.List).isRequired
  }

  constructor (props, context) {
    super(props, context)

    this._rowRenderer = this._rowRenderer.bind(this)
    this._rowRendererAdapter = this._rowRendererAdapter.bind(this)
  }

  shouldComponentUpdate (nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState)
  }

  render () {
    const { list } = this.props

    return (
      <AutoSizer>
        {({ height, width }) => (
          <CellMeasurer
            cellRenderer={this._rowRendererAdapter}
            columnCount={1}
            rowCount={list.size}
            width={width}
          >
            {({ getRowHeight }) => (
              <List
                height={height}
                rowCount={list.size}
                rowHeight={getRowHeight}
                rowRenderer={this._rowRenderer}
                width={width}
              />
            )}
          </CellMeasurer>
        )}
      </AutoSizer>
    )
  }

  _getDatum (index) {
    const { list } = this.props

    return list.get(index % list.size)
  }

  _rowRenderer ({ index, key, style }) {
    const datum = this._getDatum(index)

    return (
      <div
        key={key}
        style={style}
      >
        {datum.name /* Or whatever */}
      </div>
    )
  }

  _rowRendererAdapter ({ rowIndex, ...rest }) {
    return this._rowRenderer({
      index: rowIndex,
      ...rest
    })
  }
}
于 2016-11-08T16:22:15.297 に答える