跟着官方示例学习 @tanStack-table --- Column Ordering

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

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

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


🧱 列可见性切换

在实际项目中,我们经常需要根据用户需求隐藏不必要的列,或者让用户自由切换列的显示与否。例如:用户在查看员工信息时可能只关注姓名和职位,而不需要每次都看到访问次数或进度等辅助信息。

🧪 核心代码解析

⚙️ 1. 设置初始列定义:

tsx 复制代码
const [columns] = React.useState(() => [...defaultColumns]);

通过 useState 列定义,确保列只初始化一次。

⚙️ 2. 控制列可见性的状态:

tsx 复制代码
const [columnVisibility, setColumnVisibility] = React.useState({});

用于记录每个列的可见状态(key 是列 id,value 是 true 或 false)。

⚙️ 3. 在 useReactTable 中配置状态与回调:

tsx 复制代码
const table = useReactTable({
  data,
  columns,
  state: { columnVisibility },
  onColumnVisibilityChange: setColumnVisibility,
  getCoreRowModel: getCoreRowModel(),
});

一旦用户勾选复选框,表格状态会同步更新并触发 UI 渲染。

⚙️ 4. UI 部分实现:

全选开关:

tsx 复制代码
<input
  type="checkbox"
  checked={table.getIsAllColumnsVisible()}
  onChange={table.getToggleAllColumnsVisibilityHandler()}
/>

单列开关:

tsx 复制代码
table.getAllLeafColumns().map((column) => (
  <input
    type="checkbox"
    checked={column.getIsVisible()}
    onChange={column.getToggleVisibilityHandler()}
  />
))

getAllLeafColumns API 🔗:获取所有叶子列(leaf columns),即最终渲染到表格中的"最底层的列"。

🔔 对官方示例代码可能存在一些删减的情况

代码地址🔗:Gitee

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

✨ 列排序

在某些使用场景中,我们希望用户可以 动态调整表格列的顺序,以便根据业务需求进行自定义展示。

🔧 如何实现列顺序切换?

我们先来看最核心的两行代码:

tsx 复制代码
const [columnOrder, setColumnOrder] = React.useState<ColumnOrderState>([]);

table.setColumnOrder(
  faker.helpers.shuffle(table.getAllLeafColumns().map(d => d.id))
);

⚙️ 1. 步骤拆解:

初始化状态:

tsx 复制代码
const [columnOrder, setColumnOrder] = React.useState<ColumnOrderState>([])

columnOrder 是一个数组,表示当前列的显示顺序(每个元素是一个列 ID)。

⚙️ 2. 配置到表格中:

tsx 复制代码
const table = useReactTable({
  //...
  state: { columnOrder },
  onColumnOrderChange: setColumnOrder,
});

当列顺序发生改变时,React Table会使用你提供的onColumnOrderChange回调更新状态。

⚙️ 3. 动态修改顺序(示例是随机打乱顺序):

tsx 复制代码
table.setColumnOrder(
  faker.helpers.shuffle(table.getAllLeafColumns().map(d => d.id))
);
tsx 复制代码
// 返回所有叶子列(最底层列), 得到它们的 ID 列表
getAllLeafColumns().map(d => d.id)

// 用于打乱顺序
faker.helpers.shuffle()

最终将新的顺序通过 setColumnOrder 应用到表格中

🔔 对官方示例代码可能存在一些删减的情况

代码地址🔗:Gitee

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

🧀 列拖拽排序

🧲 用 DnD Kit 加持列排序交互

我们使用 @dnd-kit/core 来为表格添加拖拽能力

⚙️ 1. 每个列头变成可拖拽单元

我们创建了一个组件 <DraggableTableHeader />,它包裹住了每一个 <th>,并绑定了拖拽行为:

tsx 复制代码
const DraggableTableHeader = ({ header }) => {
  const { setNodeRef, listeners, attributes, transform, isDragging } = useSortable({ id: header.column.id });

  const style = {
    transform: CSS.Translate.toString(transform),
    opacity: isDragging ? 0.8 : 1,
    //...
  }

  return (
    <th ref={setNodeRef} style={style}>
      {header.isPlaceholder
        ? null
        : flexRender(header.column.columnDef.header, header.getContext())}
      <button {...attributes} {...listeners}>🟰</button>
    </th>
  )
}

这个组件使用了 useSortable,我们传入当前列的 IDDnd Kit 会帮我们处理拖拽逻辑,transform 会让列在拖动时产生动画过渡。

⚙️ 2. 将所有列头包进 <SortableContext />

SortableContextDnD Kit 的容器,它告诉系统:这一组元素是可以排序的,排序方式是"水平排列"。

tsx 复制代码
<SortableContext items={columnOrder} strategy={horizontalListSortingStrategy}>
  {headerGroup.headers.map(header => (
    <DraggableTableHeader key={header.id} header={header} />
  ))}
</SortableContext>

其中 items 是当前的列顺序(用 ID 表示),strategy 选择横向排序。

⚙️ 3. 配置 DndContext 管理拖拽行为

最外层我们包了一个 <DndContext>,这是 DnD Kit 的顶级组件,用于统一管理拖拽逻辑:

tsx 复制代码
<DndContext
  sensors={sensors}
  collisionDetection={closestCenter}
  modifiers={[restrictToHorizontalAxis]}
  onDragEnd={handleDragEnd}
>
  {/* 表格渲染 */}
</DndContext>

我们使用 closestCenter 判断碰撞区域,使用 restrictToHorizontalAxis 限制只能左右拖动。

⚙️ 4. 拖拽完成后更新 columnOrder

当用户释放拖拽时,handleDragEnd 会被触发:

tsx 复制代码
function handleDragEnd(event: DragEndEvent) {
  const { active, over } = event
  if (active && over && active.id !== over.id) {
    setColumnOrder((old) => {
      const oldIndex = old.indexOf(active.id)
      const newIndex = old.indexOf(over.id)
      return arrayMove(old, oldIndex, newIndex)
    })
  }
}

通过 arrayMove 工具函数,我们调整列的顺序数组 columnOrder,表格会自动根据新的顺序重新渲染。

⚙️ 5. 同步拖动列单元格

为了更真实的拖拽体验,不只是 <th> 头部,单元格 <td> 也要一起动。通过 <DragAlongCell /> 组件,实现列单元格的同步拖拽动画:

tsx 复制代码
const DragAlongCell = ({ cell }) => {
  const { setNodeRef, transform } = useSortable({ id: cell.column.id })
  const style = {
    transform: CSS.Translate.toString(transform),
    ...
  }
  return <td ref={setNodeRef} style={style}>{...}</td>
}

并为每一行的每一格 <td> 也包进 SortableContext 中,确保拖动时位置变化一致:

tsx 复制代码
<tr>
  {row.getVisibleCells().map(cell => (
    <SortableContext key={cell.id} items={columnOrder} strategy={horizontalListSortingStrategy}>
      <DragAlongCell key={cell.id} cell={cell} />
    </SortableContext>
  ))}
</tr>

🔔 对官方示例代码可能存在一些删减的情况

代码地址🔗:Gitee

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

相关推荐
程序视点1 小时前
IObit Uninstaller Pro专业卸载,免激活版本,卸载清理注册表,彻底告别软件残留
前端·windows·后端
前端程序媛-Tian2 小时前
【dropdown组件填坑指南】—怎么实现下拉框的位置计算
前端·javascript·vue
嘉琪0012 小时前
实现视频实时马赛克
linux·前端·javascript
烛阴2 小时前
Smoothstep
前端·webgl
十盒半价2 小时前
React 性能优化秘籍:从渲染顺序到组件粒度
react.js·性能优化·trae
若梦plus3 小时前
Eslint中微内核&插件化思想的应用
前端·eslint
爱分享的程序员3 小时前
前端面试专栏-前沿技术:30.跨端开发技术(React Native、Flutter)
前端·javascript·面试
超级土豆粉3 小时前
Taro 位置相关 API 介绍
前端·javascript·react.js·taro
若梦plus3 小时前
Webpack中微内核&插件化思想的应用
前端·webpack
若梦plus3 小时前
微内核&插件化设计思想
前端