react-virtualized - 如何将其用作真正的无限卷轴

时间:2017-07-31 04:17:59

标签: react-virtualized

我无法找到任何可以解答此问题的代码示例或文档:

  • 实现几乎完全无限滚动 - >未知的项目数量,但有一定数量的预先计算可能是不可行的 - 例如在某些时候,列表需要停止滚动
  • 我是否可以从InfiniteScroller / List中触发第一次数据加载 - 您似乎需要传入一个填充了初始页面的数据源

我正在使用这个例子: https://github.com/bvaughn/react-virtualized/blob/master/docs/creatingAnInfiniteLoadingList.md

和: https://github.com/bvaughn/react-virtualized/blob/master/source/InfiniteLoader/InfiniteLoader.example.js

以及CellMeasurer的动态高度: https://github.com/bvaughn/react-virtualized/blob/master/source/CellMeasurer/CellMeasurer.DynamicHeightList.example.js

InfiniteLoader.rowCount的文档说: "列表中的行数;如果实际数字未知,则可以是任意高数。"

那你怎么表明没有更多的行呢。

如果有人可以使用setTimeout()发布示例来模拟动态加载数据,谢谢。我很可能让CellMeasurer在那里工作。

修改

这并不像反应虚拟化的创造者所说的那样或无限加载示例所暗示的方式。

呼叫:

  • render():rowCount = 1
  • _rowRenderer(index = 0)
  • _isRowLoaded(index = 0)
  • _loadMoreRows(startIndex = 0,stopIndex = 0)
  • _rowRenderer(index = 0)

我是否需要指定批量大小或其他道具?

class HistoryBrowser extends React.Component
{
    constructor(props,context,updater)
    {
        super(props,context,updater);
        this.eventEmitter = new EventEmitter();
        this.eventEmitter.extend(this);
        this.state = {
            history: []
        };
        this._cache = new Infinite.CellMeasurerCache({
            fixedWidth: true,
            minHeight: 50
        });
        this._timeoutIdMap = {};
        _.bindAll(this,'_isRowLoaded','_loadMoreRows','_rowRenderer');

    }


    render()
    {
        let rowCount = this.state.history.length ? (this.state.history.length + 1) : 1;
        return <Infinite.InfiniteLoader
            isRowLoaded={this._isRowLoaded}
            loadMoreRows={this._loadMoreRows}
            rowCount={rowCount}
        >
            {({ onRowsRendered, registerChild }) =>
                <Infinite.AutoSizer disableHeight>
                    {({ width }) =>
                        <Infinite.List
                            ref={registerChild}
                            deferredMeasurementCache={this._cache}
                            height={200}
                            onRowsRendered={onRowsRendered}
                            rowCount={rowCount}
                            rowHeight={this._cache.rowHeight}
                            rowRenderer={this._rowRenderer}
                            width={width}
                        />}
                </Infinite.AutoSizer>}
        </Infinite.InfiniteLoader>
    }

    _isRowLoaded({ index }) {
        if (index == 0 && !this.state.history.length)
            // No data yet, force load
            return false;
    }

    _loadMoreRows({ startIndex, stopIndex }) {
        let self = this;
        for (let i = startIndex; i <= stopIndex; i++) {
            this.state.history[startIndex] = {loading: true};
        }

        const timeoutId = setTimeout(() => {
            delete this._timeoutIdMap[timeoutId];

            for (let i = startIndex; i <= stopIndex; i++) {
                self.state.history[i] = {loading: false, text: 'Hi ' + i };
            }

            promiseResolver();
        }, 10000);

        this._timeoutIdMap[timeoutId] = true;

        let promiseResolver;

        return new Promise(resolve => {
            promiseResolver = resolve;
        });
    }

    _rowRenderer({ index, key, style }) {
        let content;
        if (index >= this.state.history.length)
            return <div>Placeholder</div>
        else if (this.state.history[index].loading) {
            content = <div>Loading</div>;
        } else {
            content = (
                <div>Loaded</div>
            );
        }

        return (
            <Infinite.CellMeasurer
                cache={this._cache}
                columnIndex={0}
                key={key}
                rowIndex={index}
            >
                <div key={key} style={style}>{content}</div>
            </Infinite.CellMeasurer>
        );
    }
}

1 个答案:

答案 0 :(得分:3)

recipe you linked to应该是一个很好的起点。缺少的主要内容是loadNextPage的实现,但根据您的状态/数据管理代码的工作原理,应用程序的变化会有所不同。

  

我是否可以从InfiniteScroller / List中触发第一次数据加载 - 您似乎需要传入一个填充了初始页面的数据源

这取决于你。 IMO通常只需获取记录的第一个“页面”而无需等待InfiniteLoader请求它们 - 因为您知道您将需要它们。话虽这么说,如果你给InfiniteLoader一个rowCount,然后从isRowLoaded返回false,它应该请求第一页记录。有一些测试在反应虚拟化的GitHub中确认了这种行为。

  

InfiniteLoader.rowCount的文档说:“列表中的行数;如果实际数字未知,则可以是任意高数字。”

     

那你怎么表明没有更多的行呢。

您停止向rowCount添加+1,就像您提及的降价文件一样:

// If there are more items to be loaded then add an extra row to hold a 
loading indicator.
  const rowCount = hasNextPage
    ? list.size + 1
    : list.size