首页 > 解决方案 > react-window:如何使用实际的表格标签

问题描述

我想使用语义 HTML 标签(而不是使用 div)来创建一个带有 react-window 的表。

问题是 List (FixedSizedList) 创建了两个包装器。另一个被调用outerElementType,也是一个FixedSizedList带有默认值的道具div。这意味着我无法创建正确的表结构,并且所有结果都td在第一列中。看起来这两个都不能省略。我该如何解决这个问题?

当前代码:

import { FixedSizeList as List } from "react-window";

...

return (

   <table className="CargoListTable">
      <CargoTableHead />
      <List
        height={600}
        itemCount={cargoList.length}
        itemSize={35}
        width={900}
        itemData={cargoList}
        innerElementType="tbody"
      >
        {Row}
      </List>
   </table>
 )

const Row: React.FC<RowProps> = ({ index, style, data }) => {
  const cargo = data[index];
  return (
    <tr
      style={style}
      key={index}
    >
      <td>{cargo.registrationNumber}</td>
      <td>{cargo.pol}</td>
      <td>{cargo.pod}</td>
    </tr>
  );
};

标签: reactjsreact-window

解决方案


一种可能的解决方案是将整个表放在列表中。为此,我们可以使用react-window中的sticky-header 示例的修改版本。

您可以在此 CodeSandbox 中查看一个工作示例:https ://codesandbox.io/s/wild-dust-jtf42?file=/src/index.js

我们将需要两个简单的元素来渲染StickyRowRow元素。您可以在此处添加td元素。

const Row = ({ index, style }) => (
  <tr className="row" style={style}>
    Row {index}
  </tr>
);

const StickyRow = ({ index, style }) => (
  <tr className="sticky" style={style}>
    <th>Sticky Row {index}</th>
  </tr>
);

我们将其包装FixedSizeList在包含粘性行的 Context 中。在这种情况下,只有第一行是粘性的。

const StickyList = ({ children, stickyIndices, ...rest }) => (
  <StickyListContext.Provider value={{ ItemRenderer: children, stickyIndices }}>
    <List itemData={{ ItemRenderer: children, stickyIndices }} {...rest}>
      {ItemWrapper}
    </List>
  </StickyListContext.Provider>
);

ItemWrapper使用主渲染函数(即- {Row})中传递的方法仅渲染非粘性行。这负责呈现表数据。

const ItemWrapper = ({ data, index, style }) => {
  const { ItemRenderer, stickyIndices } = data;
  if (stickyIndices && stickyIndices.includes(index)) {
    return null;
  }
  return <ItemRenderer index={index} style={style} />;
};

要呈现表头,我们需要一个自定义的 innerElementType。

const innerElementType = forwardRef(({ children, ...rest }, ref) => (
  <StickyListContext.Consumer>
    {({ stickyIndices }) => (
      <table ref={ref} {...rest}>
        {stickyIndices.map(index => (
          <StickyRow
            index={index}
            key={index}
            style={{ top: index * 35, left: 0, width: "100%", height: 35 }}
          />
        ))}

        <tbody>
          {children}
        </tbody>
      </table>
    )}
  </StickyListContext.Consumer>
));

由于上下文,该元素知道粘性索引。并渲染标题和正文。

如果它适合您的需要,可以进一步简化此代码。


推荐阅读