10

我在 StackOverflow 上浏览了很多答案。我也在这里浏览了 List 文档react-virtualized/List。但是,我仍然无法理解如何在反应虚拟化列表中动态设置行高。如何计算rowHeightprop 函数中的高度?

我可以调用我的函数,如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')
);

任何帮助将不胜感激。谢谢!

4

2 回答 2

1

我经历了你和其他人提到的所有事情,最后,我最终创建了这个示例,我也在这里进行了解释。它Table在旁边使用react hooks,可能对其他人也有帮助。我为一些可能有一些可扩展行的表构建了这个。

于 2019-03-24T13:54:33.083 回答
0

你需要computeRowHeight自己写来确定行的高度。在某些情况下,根据该行的索引和属性,您可能能够知道该行的高度。例如,如果您的行可能是不同的组件,如果您知道某行将是高度为 40 的组件 A,而另一行将是高度为 60 的组件 B,您可以检查这些道具并返回正确的高度。

如果您不知道高度,那么您将不得不实际查看 DOM 中的元素并找出它的高度。如果它在 DOM 中尚不存在,您需要最初返回一个最佳猜测,然后在渲染后调用recomputeRowHeights并检查 DOM。

于 2016-12-30T21:28:42.280 回答