十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TanStack React Table 行展开(Expanding)功能完全指南:子行、详情面板与状态管理

TanStack React Table 行展开(Expanding)功能完全指南:子行、详情面板与状态管理 前端UI组件【免费下载链接】table Headless UI for building powerful tables datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table项目地址https://gitcode.com/gh_mirrors/ta/table点击查看免费下载行展开Expanding是 TanStack React Table 的核心交互功能之一它允许用户在当前行下方显示或隐藏与其关联的额外行数据——无论是层级结构中的子行、聚合行还是与表格数据无关的自定义详情面板。本文将基于仓库中 docs/framework/react/guide/expanding.md 指南结合 packages/table-core 的源码实现与 examples/react/expanding 完整示例系统讲解如何在 React 应用中开启客户端展开、通过getSubRows定义子行、实现自定义详情 UI、管理展开状态以及与过滤、分页、排序、分组等特性协同工作读完即可在真实项目中落地一套可用的可展开表格。一、Expanding 功能是什么Expanding行展开是 TanStack Table 的一个特性Feature它让你能够显示和隐藏与某一行相关的额外数据行。典型的应用场景有两类层级数据下钻数据本身存在父子层级关系用户可以从高层级向下钻取查看更细粒度的数据例如组织架构、目录树、账单明细。展示行关联的附加信息例如详情面板Detail Panel、子表格Sub-table、可展开行Expandable Rows等展示该行数据对象之外或之内的更多细节。从仓库源码看该功能由rowExpandingFeature特性提供核心文件位于 packages/table-core/src/features/row-expanding/rowExpandingFeature.ts它负责初始化expanded状态切片默认空映射即没有任何行被展开见 rowExpandingFeature.utils.ts为行Row实例注入toggleExpanded、getIsExpanded、getCanExpand、getIsAllParentsExpanded、getToggleExpandedHandler等 API为表格Table实例注入setExpanded、toggleAllRowsExpanded、resetExpanded、getIsAllRowsExpanded、getExpandedDepth等 API提供默认表选项onExpandedChange状态更新器与paginateExpandedRows: true见 rowExpandingFeature.ts。同时仓库内置了 examples/react/expanding 这个可直接运行查看的示例项目以及对应的端到端测试 smoke.spec.ts覆盖了展开/折叠单行、层级缩进、表头一键全展开、叶子行标记、父子行联动选择等真实交互行为是理解本文所有概念的最佳配套材料。二、Expanding 的两大使用场景TanStack Table 的展开功能主要服务于两种使用形态1. 展开子行Child Rows / Aggregate Rows数据对象本身包含嵌套的subRows例如children数组展开后子行以独立的表格行形式插入到父行下方并继承与父行相同的列结构。这是最传统的树形表格形态。2. 展开自定义 UIDetail Panels / Sub-components在行的下方渲染一段不属于列结构的自定义 UI如卡片式详情、内嵌小表格、图表等通常通过getRowCanExpand覆盖行能否展开的判断并在渲染时以跨列colSpan的单行呈现。这类 UI 在社区中有多种叫法展开行、详情面板、子组件等。这两种场景可以混合使用且对应的状态管理、切换处理 API 完全一致区别主要在于数据来源是否有真实子行与渲染方式子行复用列结构 vs 自定义跨列 UI。三、基础安装开启客户端展开在 v9 版本的 TanStack Table当前仓库即 v9 架构中功能通过tableFeatures组合子注册。开启客户端展开需要两件事rowExpandingFeature特性 createExpandedRowModel()行模型工厂。import { useTable, tableFeatures, rowExpandingFeature, createExpandedRowModel, } from tanstack/react-table const features tableFeatures({ rowExpandingFeature, expandedRowModel: createExpandedRowModel(), // 客户端展开注册展开行模型 // manualExpanding: true, // 服务端展开改为手动展开 }) const table useTable({ features, columns, data, })要点说明rowExpandingFeature注册展开状态与所有展开相关 APIexpandedRowModel注册展开行模型工厂。由于行模型槽位是类型检查的row model slots are type-checked客户端展开时必须紧跟在 feature 之后注册它否则类型与运行时都拿不到展开后的行模型若使用服务端手动展开则无需注册expandedRowModel而是开启manualExpanding: true在服务端自行完成行展开。在 examples/react/expanding/src/main.tsx 中可以看到更完整的组合展开、过滤、分页、排序、行选择五个特性同时启用分别对应expandedRowModel、filteredRowModel、paginatedRowModel、sortedRowModel四个行模型槽位。四、把表格行作为展开数据getSubRows当你的数据对象已经包含嵌套的子行数据时用getSubRows告诉表格去哪找子行。例如下面的层级人物数据type Person { id: number name: string age: number children?: Person[] | undefined } const data: Person[] [ { id: 1, name: John, age: 30, children: [ { id: 2, name: Jane, age: 5 }, { id: 5, name: Jim, age: 10 }, ], }, { id: 3, name: Doe, age: 40, children: [{ id: 4, name: Alice, age: 10 }], }, ]然后在表选项里把每个行的children数组交给getSubRowsconst table useTable({ features, getSubRows: (row) row.children, // 返回 children 数组作为子行 // other options... })表格实例此后就会在每个行上查找children将其作为可展开的子行。示例项目中的数据类型与此一致——Person的subRows?: ArrayPerson字段配合getSubRows: (row) row.subRows见 makeData.ts 与 main.tsx。[!NOTE]getSubRows可以写得比较复杂但请记住它会对每一行、每一级子行都执行。如果函数未经优化例如做了深拷贝或复杂计算在大数据量下会非常昂贵。另外不支持异步函数。一个从源码可以印证的行为展开行模型在计算时会把被展开的行的subRows递归压平插入到当前行序列中见 createExpandedRowModel.ts 的expandRows实现因此渲染阶段拿到的table.getRowModel().rows已经是父行 展开后的子行交错的扁平序列这也就是为什么示例代码里可以直接用row.depth的paddingLeft做视觉缩进。五、自定义展开 UI详情面板有些场景下你要展开的内容不是新的表格行而是一段独立的 UI——它可能来自表格数据对象也可能完全无关。这时需要覆盖哪些行可以展开的判断。默认情况下row.getCanExpand()只有在行上存在subRows时才返回true。你可以通过表选项getRowCanExpand完全接管这个判断import { Fragment } from react //... const table useTable({ features, getRowCanExpand: (row) true, // 自行决定哪些行可展开这里表示所有行都有展开内容 // other options... }) //... tbody {table.getRowModel().rows.map((row) ( Fragment key{row.id} {/* 普通行 UI */} tr {row.getVisibleCells().map((cell) ( td key{cell.id} table.FlexRender cell{cell} / /td ))} /tr {/* 当行被展开时渲染展开 UI单独一行、单格跨整表宽度 */} {row.getIsExpanded() ( tr {/* 若展开内容不共享父行的列结构colSpan 取整表列数 */} td colSpan{row.getAllCells().length} {/* 你的自定义 UI 放在这里 */} /td /tr )} /Fragment ))} /tbody //...这一模式的要点使用 React 的Fragment让普通行 详情行成为同一行的两个兄弟节点详情行渲染为单独tr内部单td通过colSpan{row.getAllCells().length}跨越整表宽度row.getIsExpanded()控制是否渲染详情行。从源码看row.getCanExpand()的默认逻辑是enableExpanding ?? true与!!row.subRows.length的与运算而getRowCanExpand一旦提供会优先于默认逻辑见 rowExpandingFeature.utils.ts。因此自定义 UI 场景下务必提供getRowCanExpand否则没有子行的行将永远无法展开。六、管理展开状态expanded state展开状态是一个名为expanded的状态切片类型定义如下type ExpandedState true | Recordstring, boolean值为true所有行都展开值为Recordstring, boolean只有键为行 ID 且值为true的行被展开。例如{ row1: true, row2: false }表示row1展开、row2不展开。表格依据该状态决定哪些行显示它们的子行。方式一外部 Atomv9 推荐如果应用的其他部分需要读取展开状态v9 推荐通过atoms表选项传入外部 atom。Atom 支持细粒度订阅展开值可以在应用的任意位置被读取而不会强制持有表格的组件重新渲染。import { useCreateAtom, useSelector } from tanstack/react-store const expandedAtom useCreateAtomExpandedState({}) // 在任何需要的地方订阅 atom const expanded useSelector(expandedAtom) const table useTable({ features, // other options... atoms: { expanded: expandedAtom, // 展开相关 API 将更新 expandedAtom }, })方式二受控 state onExpandedChangev8 风格v8 风格的state.expandedonExpandedChange模式仍然受支持适合简单集成或 v8 代码迁移场景但粒度不如外部 atom 精细。两种方式的取舍详见 Table State Guide。const [expanded, setExpanded] useStateExpandedState({}) const table useTable({ features, // other options... state: { expanded, }, onExpandedChange: setExpanded, })在 examples/react/expanding/src/main.tsx 的注释中可以看到两种方式的等价写法以及initialState: { expanded: { 0: true } }首屏默认展开第一行这类初始化技巧。七、为展开行添加 UI 切换按钮TanStack Table不会自动为你添加展开/折叠的切换 UI需要你在每一行的 UI 中自行添加。最典型的方式是在列定义中放一个按钮const columns [ { accessorKey: name, header: Name, }, { accessorKey: age, header: Age, }, { header: Children, cell: ({ row }) { return row.getCanExpand() ? ( button onClick{row.getToggleExpandedHandler()} style{{ cursor: pointer }} {row.getIsExpanded() ? : } /button ) : ( ) }, }, ]示例项目更进一步把展开按钮放进 First Name 单元格用row.depth * 2rem的paddingLeft呈现层级缩进并用 标记没有子行的叶子行见 main.tsx。端到端测试 smoke.spec.ts 验证了该缩进效果根行padding-left: 0px第一级子行28px2rem × 14px 根字号第二级56px。八、Expanding API 速查行Row实例 APIrow.getCanExpand() // 该行能否展开 row.getIsExpanded() // 该行是否已展开 row.getIsAllParentsExpanded() // 该行的所有祖先是否都已展开 row.getToggleExpandedHandler() // 返回一个切换展开的点击处理器不可展开时是 no-op row.toggleExpanded() // 编程式切换展开状态可传 true/false 强制指定表格Table实例 APItable.getCanSomeRowsExpand() // 是否存在至少一个可展开的行分页前判断 table.getIsAllRowsExpanded() // 是否所有可展开行都已展开 table.getIsSomeRowsExpanded() // 是否至少有一行展开 table.getExpandedDepth() // 当前展开的最大深度 table.getToggleAllRowsExpandedHandler() // 全选/全不选展开的点击处理器 table.toggleAllRowsExpanded() // 编程式切换全部展开 table.resetExpanded() // 重置展开状态补充说明均有源码依据见 rowExpandingFeature.utils.tstable.setExpanded用于直接更新展开状态接收true、行 ID 映射或更新函数L66-L75table.resetExpanded()重置为initialState.expandedtable.resetExpanded(true)忽略初始状态直接清空为{}L120-L137table.getCanSomeRowsExpand()基于分页前的行模型判断因此表头展开按钮能正确反映当前页之外也存在可展开行的情况L150-L157当展开状态是true全部展开时对单行调用toggleExpanded会先把全展开物化为只含可展开行 ID 的映射再应用行级变更保证两种状态表示语义等价L289-L335table.toggleAllRowsExpanded()在没有任何可展开行、或请求状态与当前状态一致时不会触发任何更新no-opL92-L106。九、与其他特性的协同1. 过滤展开行Filtering默认过滤方向是从父行往下父行被过滤掉其所有子行一并排除。可通过filterFromLeafRows反转方向——从叶子子行向上过滤只要任一子行/孙行命中条件父行就保留maxLeafRowFilterDepth则限定过滤考虑的子行最大深度。const features tableFeatures({ columnFilteringFeature, rowExpandingFeature, filteredRowModel: createFilteredRowModel(), expandedRowModel: createExpandedRowModel(), filterFns, }) //... const table useTable({ features, getSubRows: (row) row.subRows, filterFromLeafRows: true, // 过滤时搜索展开的行自下而上 maxLeafRowFilterDepth: 1, // 限制被搜索的展开行深度 // other options... })2. 分页展开行Pagination默认情况下展开的子行随整表一起分页即展开行可能跨越多个页面。设置paginateExpandedRows: false可关闭该行为展开行将始终渲染在父行所在的页面上副作用是每页渲染的行数可能超过设置的 pageSize。const table useTable({ features, // other options... paginateExpandedRows: false, })从源码看createExpandedRowModel会在paginateExpandedRows: false且非手动分页时跳过展开交由分页模型在父行之后原位插入子行见 createExpandedRowModel.ts。默认值paginateExpandedRows: true由rowExpandingFeature的默认选项提供见 rowExpandingFeature.ts。3. 固定展开行Row Pinning展开行的固定与普通行固定方式完全相同可将展开行固定到表格顶部或底部。详见 Row Pinning Guide。4. 排序展开行Sorting默认情况下展开的行随整表一起排序。十、自动重置展开状态Auto Reset若同时使用分组grouping特性expanded状态会在分组行模型重算时如data或分组状态变化自动重置。该默认行为在manualExpanding: true时自动禁用但可通过显式给autoResetExpanded赋值覆盖。另有全局的autoResetAll选项可一次性开关所有特性的自动重置。一个常见的关闭场景是边查看边编辑数据例如单元格内联编辑每次编辑都会更新data并重算行模型默认行为会把用户已展开的行全部收起。此时应设置const table useTable({ features, // other options... autoResetExpanded: false, // data 变化时保持展开状态 // autoResetAll: false, // 或一次性关闭所有自动重置 })如果同时使用分页特性建议搭配autoResetPageIndex: false以同时保持当前页码不跳回第一页。相关重置逻辑见 rowExpandingFeature.utils.ts只有当autoResetAll、autoResetExpanded或默认客户端展开行为允许时才会调度一次展开状态重置。十一、手动服务端展开若做服务端展开将manualExpanding设为true此时表格不再使用getExpandedRowModel展开行需要你在自己的数据模型中完成展开逻辑例如服务端返回已展开的行列表。const features tableFeatures({ rowExpandingFeature }) const table useTable({ features, // other options... manualExpanding: true, })注意此模式下无需也不应注册expandedRowModel表格的展开 API 仍然可用仅用于管理状态实际行展开由你的数据层负责。十二、完整示例与验证仓库提供了可直接运行与测试的完整示例 examples/react/expanding其中main.tsx 组合了展开、过滤、分页、排序、行选择五大特性数据为makeData(100, 5, 3)100 个根行每行 5 个子行每个子行 3 个孙行包含行级与表头级的展开切换按钮、深度缩进、防抖过滤输入、分页控件与状态调试面板debugTable/debugRowsmakeData.ts 演示了如何递归生成任意深度的层级数据Person类型含可选的subRowssmoke.spec.ts 用 Playwright 端到端验证了初始无展开、单行展开/折叠、按深度逐级缩进、表头一键全展开展开状态变为true、无子行的叶子行显示标记、以及选中父行级联选中整棵子树等交互。运行方式仓库根目录先安装依赖再进入examples/react/expanding目录启动 Vite 开发服务器即可在浏览器中交互体验pnpm test或对应 workspace 脚本可运行其端到端测试。结语行展开是构建层级表格与详情交互的基石能力。本文从 docs/framework/react/guide/expanding.md 出发结合 packages/table-core 的实现与 examples/react/expanding 的完整示例覆盖了特性注册、getSubRows子行数据、自定义详情面板、两种状态管理方式、切换按钮、API 速查以及与过滤/分页/固定/排序/分组/自动重置的协同配置。掌握这些内容后无论是树形下钻还是详情展开你都能在 TanStack React Table 中快速落地生产级实现。赞分享前端UI组件【免费下载链接】table Headless UI for building powerful tables datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table项目地址https://gitcode.com/gh_mirrors/ta/table点击查看免费下载相关推荐TanStack Alpine Table 行展开Expanding功能实战指南子行、详情面板与状态管理TanStack Alpine Table 行展开Expanding功能实战指南子行、详情面板与状态管理 TanStack Alpine Table 的前端UI组件CANN/AscendC MakeTensor接口MakeTensor 产品支持情况 | 产品 | 是否支持 | | : | : : | | Ascend 950PR/Ascend 950DT | √ | 功能前端UI组件TanStack Table Preact 行展开Expanding完整指南从子行钻取到详情面板的实战实现TanStack Table Preact 行展开Expanding完整指南从子行钻取到详情面板的实战实现 本指南以 TanStack TablePre前端UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表