【问题标题】:React Virtualized - Nested WindowScroller/ListReact Virtualized - 嵌套的 WindowScroller/List
【发布时间】:2019-02-17 18:22:37
【问题描述】:

我正在尝试使用 react-virtualized 来呈现包含 1000 多行数据的表格。这些行非常重,包含多个复杂的 React 组件。输入、组合框、日期选择器和弹出菜单都在一行中。我需要整个窗口来滚动这些行。

我还需要对行进行分组并将它们嵌套到一个显示/隐藏样式的手风琴组件中。

[+] Row Header 1
    row 1
    row 2
    ...
    row 1001
[+] Row Header 2
    row 1
    row 2
    ...
    row 1001

我不确定如何处理这种用例,或者 React-Virtualized 是否可以处理这种类型的事情。

我的尝试:

结合使用 WindowScroller/AutoSizer/List 组件,并将这组 react-virtualized 组件放入每个手风琴中。这有效,但不能解决我的问题。问题,因为浏览器仍然无法处理(第一次加载大约 25 秒,滚动不可用)

是否还需要使用 WindowScroller/AutoSizer/List 组件来处理第一级 Row Headers?

任何想法或示例将不胜感激。

【问题讨论】:

  • 现在在同一个问题上。你有没有找到一个很好的解决方案来分享?目前正在考虑两种可能的选择:1)在每个级别上使用虚拟化网格(当行展开时,组网格和子项网格)2)仅使用一个虚拟化网格,将我的数据准备为树状结构,只需更改 rowCount展开项目时
  • 您是否需要显示所有这些组件,或者您只有一个稍后会展开以显示复杂组件结构的标题?

标签: javascript reactjs react-virtualized


【解决方案1】:

您至少可以腾出 UI 线程来使用 Web Worker 进行滚动(当然这是一个重要的 UX 原则)。

这是medium-length discussion article with an examplequick implementation doc(和the great matching article)和my all-time favorite talk on the subject

这会延迟主“UI”线程的工作,但如果可以使用useMemo() 挂钩来记忆工作,您也可以首先防止这种延迟。

【讨论】:

    【解决方案2】:

    react-virtualized 的关键部分是recomputeRowHeights 这样就可以达到预期的效果了。

    import React, { useState, useRef, useEffect } from "react";
    import {
      AutoSizer,
      Column,
      Table,
      defaultTableRowRenderer
    } from "react-virtualized";
    
    const Component = ({ list }) => {
      const [selectedIndex, setSelectedIndex] = useState(-1);
      const tableRef = useRef();
    
      const Details = ({ children, index }) => (
        <div style={{ cursor: "pointer" }} onClick={() => setSelectedIndex(index)}>
          {children}
        </div>
      );
    
      const _getDatum = index => list[index % list.length];
      const _getRowHeight = ({ index }) => (index === selectedIndex ? 96 : 48);
      const rowGetter = ({ index }) => _getDatum(index);
      const cellRenderer = ({ rowIndex }) => {
        if (rowIndex !== selectedIndex) {
          return <Details index={rowIndex}>+</Details>;
        } else {
          return <Details index={-1}>-</Details>;
        }
      };
    
      useEffect(
        () => {
          tableRef.current.recomputeRowHeights();
        },
        [selectedIndex]
      );
    
      const rowRenderer = props => {
        const { index, style, className, key, rowData } = props;
        if (index === selectedIndex) {
          return (
            <div
              style={{ ...style, display: "flex", flexDirection: "column" }}
              className={className}
              key={key}
            >
              {defaultTableRowRenderer({
                ...props,
                style: { width: style.width, height: 48 }
              })}
              <div
                style={{
                  marginRight: "auto",
                  marginLeft: 80,
                  height: 48,
                  display: "flex",
                  alignItems: "center"
                }}
              >
                {rowData.details}
              </div>
            </div>
          );
        }
        return defaultTableRowRenderer(props);
      };
    
      return (
        <div style={{ height: "90vh" }}>
          <AutoSizer>
            {({ width, height }) => (
              <Table
                ref="Table"
                headerHeight={56}
                height={height}
                overscanRowCount={10}
                rowHeight={_getRowHeight}
                rowGetter={rowGetter}
                rowCount={1000}
                width={width}
                ref={tableRef}
                rowRenderer={rowRenderer}
              >
                <Column
                  label="Index"
                  cellDataGetter={({ rowData }) => rowData.length}
                  cellRenderer={cellRenderer}
                  dataKey="index"
                  disableSort
                  width={60}
                />
                <Column dataKey="name" disableSort label="Full Name" width={120} />
              </Table>
            )}
          </AutoSizer>
        </div>
      );
    };
    
    export default Component;

    这里是codesandbox

    【讨论】:

      猜你喜欢
      • 2016-12-03
      • 2017-04-26
      • 1970-01-01
      • 2018-10-23
      • 1970-01-01
      • 2017-06-25
      • 2017-04-20
      • 2018-07-13
      • 1970-01-01
      相关资源
      最近更新 更多