跟着官方示例学习 @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

相关推荐
山河木马几秒前
前端学习C++之:创建对象
前端·javascript·c++
汪子熙4 分钟前
web 应用本地开发中的 LiveReload 协议深度解析
前端·javascript
UI设计和前端开发从业者5 分钟前
大数据时代UI前端的智能化转型之路:以数据为驱动的产品创新
大数据·前端·ui
全宝18 分钟前
前端也能这么丝滑!Node + Vue3 实现 SSE 流式文本输出全流程
前端·javascript·node.js
前端小巷子32 分钟前
Web缓存:原理、策略与优化
前端·面试
小磊哥er34 分钟前
【前端工程化】前端工作中如何协同管理开发任务?
前端
程序员小白条39 分钟前
我的第二份实习,学校附近,但是干前端!
java·开发语言·前端·数据结构·算法·职场和发展
编程大全39 分钟前
2025年前端面试题
前端
萌萌哒草头将军1 小时前
🔥🔥🔥 NuxtLabs 宣布加入了 Vercel !
前端·javascript·vue.js
LuciferHuang8 小时前
震惊!三万star开源项目竟有致命Bug?
前端·javascript·debug