🌲系列一:跟着官方示例学习 @tanStack-table --- Basic
🌲系列二:跟着官方示例学习 @tanStack-table --- Header Groups
🌲系列三:跟着官方示例学习 @tanStack-table --- Column Filters
🌲系列四:跟着官方示例学习 @tanStack-table --- Column Ordering
🌲系列五:跟着官方示例学习 @tanStack-table ---Sticky Column Pinning
Resizing
在前面的几篇文章里,我们已经让表格列会动、会钉、会排序。这一篇,我们要再给它加上一个超能力:
✨ 列宽可以自由调整(Resizing)! —— 没错,就是像 Excel 一样,用户可以手动拖动边缘,改变列宽度!
🧩 基础代码
const table = useReactTable({
data,
columns,
columnResizeMode,
getCoreRowModel: getCoreRowModel(),
});
🔧 列宽调整的两种模式
可以选择两种调整列宽的体验方式:
const [columnResizeMode, setColumnResizeMode] = useState<ColumnResizeMode>("onChange");
<select onChange={(e) => setColumnResizeMode(e.target.value as ColumnResizeMode)}>
<option value="onEnd">Resize: "onEnd"</option>
<option value="onChange">Resize: "onChange"</option>
</select>
-
onChange:拖动过程中实时调整列宽
-
onEnd:拖动结束后才更新列宽
🛠️ 重头戏:头部单元格如何变宽?
<th
key={header.id}
style={{ width: header.getSize() }}
>
{/* 表头内容 */}
<div
onMouseDown={header.getResizeHandler()}
onTouchStart={header.getResizeHandler()}
className={`resizer ltr ${header.column.getIsResizing() ? "isResizing" : ""}`}
style={{
transform:
columnResizeMode === "onEnd" && header.column.getIsResizing()
? `translateX(${table.getState().columnSizingInfo.deltaOffset ?? 0}px)`
: "",
}}
/>
</th>
🧪 这里发生了什么魔法?
-
header.getSize():实时获取当前列的宽度(Table状态 →DOM映射) -
header.getResizeHandler():绑定鼠标/触摸拖动事件 -
table.getState().columnSizingInfo.deltaOffset:在onEnd模式下,提供“拖动预览”效果; -
transform:translateX(...):让拖动的手柄跟着鼠标移动,视觉反馈一流!
🪣 列宽同步到数据单元格
别忘了 <td> 也需要设置 width,否则只会看到头部变化,内容不对齐。
<td
key={cell.id}
style={{
width: cell.column.getSize(),
}}
>
🔄 一键恢复默认列宽
支持双击把手,恢复默认宽度:
onDoubleClick={() => header.column.resetSize()}
🔍 Resizing 的脑回路长这样
1. 用户拖动 .resizer
⬇️
2. 触发 getResizeHandler()
⬇️
3. 根据 columnResizeMode 更新列宽状态
⬇️
4. 使用 getSize() 显示新宽度
⬇️
5. 在 "onEnd" 模式下,deltaOffset 提供视觉预览
📺 实际演示
🔔 对官方示例代码可能存在一些删减的情况
代码地址🔗:Gitee
官方代码地址🔗: @tanStack/react-table
⚓ resize direction
官方示例代码中提到了一个可以改变方向的属性:columnResizeDirection API🔗
🧩 基础代码
const table = useReactTable({
data,
columns,
columnResizeDirection,
getCoreRowModel: getCoreRowModel(),
});
'ltr': 左 ➡️ 右
'rtl': 右 ➡️ 左
✈️ 结合 CSS 实现效果
<div style={{ direction: table.options.columnResizeDirection }}>
<div className="overflow-x-auto">
<table />
</div>
</div>
📺 实际演示