Lzh on GitHub

示例

想跳过直接看实现?请查看这些示例:

列大小调整指南

列大小调整功能允许您选择性地指定每列的宽度,包括最小和最大宽度。它还允许您和您的用户随意动态更改所有列的宽度,例如通过拖动列标题。

列宽

列默认具有以下测量选项:

export const defaultColumnSizing = {
  size: 150,
  minSize: 20,
  maxSize: Number.MAX_SAFE_INTEGER,
}

这些默认值可以被 tableOptions.defaultColumn 和单个列定义覆盖,按此顺序。

const columns = [
  {
    accessorKey: 'col1',
    size: 270, // 为此列设置列大小
  },
  //...
]

const table = useReactTable({
  // 覆盖默认列大小设置
  defaultColumn: {
    size: 200, // 初始列大小
    minSize: 50, // 列调整大小时强制执行
    maxSize: 500, // 列调整大小时强制执行
  },
})

列的“大小”以数字形式存储在表格状态中,通常被解释为像素单位值,但您可以根据需要将这些列大小值连接到您的 CSS 样式。

作为一种无头工具,列大小调整的表格逻辑实际上只是一系列状态,您可以根据需要将其应用于您自己的布局(我们上面的示例实现了这两种逻辑样式)。您可以通过多种方式应用这些宽度测量:

  • 语义化的 <table> 元素或任何以表格 CSS 模式显示的元素
  • <div>/<span> 元素或任何以非表格 CSS 模式显示的元素
  • 具有严格宽度的块级元素
  • 具有严格宽度的绝对定位元素
  • 具有宽松宽度的 Flexbox 定位元素
  • 具有宽松宽度的 Grid 定位元素

实际上,任何可以将单元格宽度插入表格结构中的布局机制都可以。

每种方法都有其自身的权衡和限制,这些通常是 UI/组件库或设计系统所持的观点,幸运的是您不必担心 😉。

列调整大小

TanStack Table 提供了内置的列调整大小状态和 API,让您可以轻松地在表格 UI 中实现列调整大小功能,并提供各种 UX 和性能选项。

启用列调整大小

默认情况下,column.getCanResize() API 会对所有列返回 true,但您可以通过 enableColumnResizing 表格选项禁用所有列的调整大小,或者通过 enableResizing 列选项逐列禁用调整大小。

const columns = [
  {
    accessorKey: 'id',
    enableResizing: false, // 仅禁用此列的调整大小
    size: 200, // 初始列大小
  },
  //...
]

列调整大小模式

默认情况下,列调整大小模式设置为 "onEnd"。这意味着 column.getSize() API 直到用户完成列调整大小(拖动)后才会返回新的列大小。通常,在用户调整列大小时会显示一个小小的 UI 指示器。

在 React TanStack Table 适配器中,根据表格或网页的复杂性,实现 60 fps 的列调整大小渲染可能很困难,因此 "onEnd" 列调整大小模式可以是一个很好的默认选项,以避免用户调整列大小时出现卡顿或延迟。这并不是说在使用 TanStack React Table 时无法实现 60 fps 的列调整大小渲染,但您可能需要进行一些额外的 memoization 或其他性能优化才能实现。

更高级的列调整大小性能技巧将在下方讨论。

如果您想将列调整大小模式更改为 "onChange" 以实现即时列调整大小渲染,您可以通过 columnResizeMode 表格选项来实现。

const table = useReactTable({
  //...
  columnResizeMode: 'onChange', // 将列调整大小模式更改为 "onChange"
})

列调整大小方向

默认情况下,TanStack Table 假定表格标记是按从左到右的方向布局的。对于从右到左的布局,您可能需要将列调整大小方向更改为 "rtl"

const table = useReactTable({
  //...
  columnResizeDirection: 'rtl', // 对于某些语言环境,将列调整大小方向更改为 "rtl"
})

连接列调整大小 API 到 UI

有一些非常方便的 API,您可以用来将列调整大小的拖动交互连接到您的 UI。

列大小 API

要将列的大小应用于列标题单元格、数据单元格或页脚单元格,您可以使用以下 API:

header.getSize()
column.getSize()
cell.column.getSize()

如何将这些大小样式应用于您的标记取决于您,但通常使用 CSS 变量或内联样式来应用列大小。

<th
  key={header.id}
  colSpan={header.colSpan}
  style={{ width: `${header.getSize()}px` }}
>

尽管,如高级列调整大小性能部分所讨论的,您可能需要考虑使用 CSS 变量将列大小应用于您的标记。

列调整大小 API

TanStack Table 提供了一个预构建的事件处理程序,使您的拖动交互易于实现。这些事件处理程序只是方便函数,用于调用其他内部 API 来更新列大小状态并重新渲染表格。使用 header.getResizeHandler() 将其连接到您的列调整大小拖动交互,包括鼠标和触摸事件。

<ColumnResizeHandle
  onMouseDown={header.getResizeHandler()} // 用于桌面
  onTouchStart={header.getResizeHandler()} // 用于移动设备
/>
带有 ColumnSizingInfoState 的列调整大小指示器

TanStack Table 跟踪一个名为 columnSizingInfo 的状态对象,您可以使用它来渲染列调整大小指示器 UI。

<ColumnResizeIndicator
  style={{
    transform: header.column.getIsResizing()
      ? `translateX(${table.getState().columnSizingInfo.deltaOffset}px)`
      : '',
  }}
/>

高级列调整大小性能

如果您正在创建大型或复杂的表格(并且正在使用 React 😉),您可能会发现,如果您不正确地对渲染逻辑进行 memoization,您的用户在调整列大小时可能会遇到性能下降的问题。

我们创建了一个高性能列调整大小示例,演示了如何在复杂的表格中实现 60 fps 的列调整大小渲染,否则这些表格可能会出现渲染缓慢的情况。建议您直接查看该示例以了解其实现方式,但这些是需要记住的基本事项:

  • 不要在每个标题和每个数据单元格上都使用 column.getSize()。相反,一次性计算所有列宽,并进行 memoization!
  • 在调整大小进行中时,对表格体进行 memoization
  • 使用 CSS 变量将列宽传达给表格单元格。

如果您遵循这些步骤,您应该会在调整列大小时看到显著的性能改进。

如果您没有使用 React,而是使用 Svelte、Vue 或 Solid 适配器,您可能不需要过多担心这一点,但类似的原则也适用。