跟着官方示例学习 @tanStack-table --- Row Pinning

🌲系列一:跟着官方示例学习 @tanStack-table --- Basic

🌲系列二:跟着官方示例学习 @tanStack-table --- Header Groups

🌲系列三:跟着官方示例学习 @tanStack-table --- Column Filters

🌲系列四:跟着官方示例学习 @tanStack-table --- Column Ordering

🌲系列五:跟着官方示例学习 @tanStack-table --- Sticky Column Pinning

🌲系列六:跟着官方示例学习 @tanStack-table --- Column Sizing

🌲系列七:跟着官方示例学习 @tanStack-table --- Expanding

🌲系列八:跟着官方示例学习 @tanStack-table --- Pagination

🌲系列九:跟着官方示例学习 @tanStack-table --- Row Dnd


📌 固定某一行?Row Pinning 来帮你!

有时候,用户想把"最重要的那几条数据"钉在表格顶部或底部,比如:

  • 总结统计行

  • 当前任务的高优先级事项

  • 某位特别"显眼"的 VIP 用户

这时候就轮到 @tanstack/react-tableRow Pinning 功能登场啦!

🧠 Row Pinning 是什么?

Row Pinning 是指将某些行固定在表格顶部(top)或底部(bottom),不受分页、排序或滚动的影响。 这与常见的"header 固定"不一样,我们这次是固定行,而不是列或表头。

🧩 基础状态管理

我们先为表格添加 rowPinning 状态:

tsx 复制代码
const [rowPinning, setRowPinning] = React.useState<RowPinningState>({
  top: [],
  bottom: [],
});

然后在 useReactTable 中绑定这两个字段:

tsx 复制代码
const table = useReactTable({
  data,
  columns,
  state: { rowPinning },
  onRowPinningChange: setRowPinning,
  getCoreRowModel: getCoreRowModel(),
});

🧲 Pin 按钮:行控制面板!

我们给每一行加上 Pin 按钮,当点击时可以把行钉到 top / bottom:

tsx 复制代码
{
  id: "pin",
  header: () => "Pin",
  cell: ({ row }) =>
    row.getIsPinned() ? (
      <button onClick={() => row.pin(false)}>❌</button>
    ) : (
      <div style={{ display: "flex", gap: "4px" }}>
        <button onClick={() => row.pin("top")}>⬆️</button>
        <button onClick={() => row.pin("bottom")}>⬇️</button>
      </div>
    ),
}
  • row.getIsPinned():返回 "top""bottom"false

  • row.pin(position):将一行固定到"顶部"或"底部",如果传入 false 则将该行解除固定到中心。

🧱 表格分段渲染:Top / Center / Bottom

我们要分别渲染 3 段行:

tsx 复制代码
<tbody>
  {table.getTopRows().map((row) => (
    <PinnedRow key={row.id} row={row} table={table} />
  ))}

  {table.getCenterRows().map((row) => (
    <tr key={row.id}>
      {row.getVisibleCells().map((cell) => (
        <td key={cell.id}>
          {flexRender(cell.column.columnDef.cell, cell.getContext())}
        </td>
      ))}
    </tr>
  ))}

  {table.getBottomRows().map((row) => (
    <PinnedRow key={row.id} row={row} table={table} />
  ))}
</tbody>
  • getTopRows(): 返回被钉在顶部的行

  • getCenterRows(): 返回正常的、未钉住的行

  • getBottomRows(): 返回被钉在底部的行

📌 PinnedRow:钉住的行要特别处理!

tsx 复制代码
function PinnedRow({ row, table }: { row: Row<any>; table: Table<any> }) {
  return (
    <tr
      style={{
        backgroundColor: "lightblue",
        position: "sticky",
        top:
          row.getIsPinned() === "top"
            ? `${row.getPinnedIndex() * 26 + 48}px`
            : undefined,
        bottom:
          row.getIsPinned() === "bottom"
            ? `${
                (table.getBottomRows().length - 1 - row.getPinnedIndex()) * 26
              }px`
            : undefined,
      }}
    >
      {row.getVisibleCells().map((cell) => (
        <td key={cell.id}>
          {flexRender(cell.column.columnDef.cell, cell.getContext())}
        </td>
      ))}
    </tr>
  );
}

我们用了 position: stickypinned 行始终在视野范围内,row.getPinnedIndex() 告诉你它是第几个被 pin 的。

官方代码地址🔗: @tanStack/react-table

🚀 Row Pinning 进阶技巧:行固定状态的持久化

🔄 Keep Pinned Rows:钉住之后不怕翻页!

场景: 用户翻页、过滤数据后,钉住的行就"消失"了?!

你可以通过以下配置让 pinned 行持久存在:

tsx 复制代码
keepPinnedRows: true

🔧 这就让 pinned 行在任何筛选、翻页后都不会被清除,是不是很贴心?

🌳 2. Include Leaf Rows / Parent Rows:树形结构的固定控制

如果你在使用嵌套数据(也就是 getSubRows),你一定会遇到这种情况:

"我钉住一个父节点,它下面的子节点要不要跟着一起固定?"

或者反过来:

"我钉住一个子节点,它的父节点也要固定吗?"

你可以通过两个配置来控制这类行为:

  • includeLeafRows: 当固定父节点时,是否自动固定它的所有叶子子节点

  • includeParentRows: 当固定一个子节点时,是否自动固定它的父节点

tsx 复制代码
<input
  type="checkbox"
  checked={includeLeafRows}
  onChange={() => setIncludeLeafRows(!includeLeafRows)}
/>
<label>Include Leaf Rows When Pinning Parent</label>

<input
  type="checkbox"
  checked={includeParentRows}
  onChange={() => setIncludeParentRows(!includeParentRows)}
/>
<label>Include Parent Rows When Pinning Child</label>

这两个参数都会作为 row.pin() 的参数传入,用来控制行为:

tsx 复制代码
row.pin("top", includeLeafRows, includeParentRows)

🪞 3. Copy Pinned Rows:固定了还要在中间再来一份?

默认情况下,getCenterRows() 只返回未被钉住的行。如果你想在中间区域也保留 pinned 行的副本,可以设置:

tsx 复制代码
copyPinnedRows: true

然后用条件渲染逻辑:

tsx 复制代码
{(copyPinnedRows
  ? table.getRowModel().rows  // 所有行,包括 pinned
  : table.getCenterRows()     // 只显示未 pinned 的行
).map(...)}

🔁 这样用户即使滚动表格,也能一直看到 pinned 行的副本,非常适合对比查看!

官方代码地址🔗: @tanStack/react-table

相关推荐
Net蚂蚁代码27 分钟前
Angular入门的环境准备步骤工作
前端·javascript·angular.js
小着3 小时前
vue项目页面最底部出现乱码
前端·javascript·vue.js·前端框架
lichenyang4535 小时前
React ajax中的跨域以及代理服务器
前端·react.js·ajax
呆呆的小草5 小时前
Cesium距离测量、角度测量、面积测量
开发语言·前端·javascript
一 乐6 小时前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
testleaf7 小时前
前端面经整理【1】
前端·面试
好了来看下一题7 小时前
使用 React+Vite+Electron 搭建桌面应用
前端·react.js·electron
啃火龙果的兔子7 小时前
前端八股文-react篇
前端·react.js·前端框架
小前端大牛马7 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js
刺客-Andy7 小时前
React第六十二节 Router中 createStaticRouter 的使用详解
前端·javascript·react.js