ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

TanStack Alpine Table 列显隐(Column Visibility)功能实践指南:从状态管理到渲染集成

TanStack Alpine Table 列显隐(Column Visibility)功能实践指南:从状态管理到渲染集成 TanStack Alpine Table 列显隐Column Visibility功能实践指南从状态管理到渲染集成【免费下载链接】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 Table v9 体系下 Alpine 适配层tanstack/alpine-table的列显隐功能展开讲解如何通过columnVisibilityFeature为表格启用列隐藏/显示能力并结合Alpine.reactive、tanstack/store外部 atom 与受控state三种状态所有权方案构建可持久化、可交互的列显隐 UI。读者完成本文后将掌握columnVisibility状态的语义与优先级规则、列级与表级显隐 API 的完整用法以及在 Alpine 模板中渲染可见性感知表头与表体的正确方式。本文对应的完整可运行示例位于 examples/alpine/column-visibility其功能实现源码位于 packages/table-core/src/features/column-visibility/columnVisibilityFeature.ts。启用列显隐功能tanstack/alpine-table是 TanStack Table v9 的 Alpine.js 适配层列显隐能力由核心包tanstack/table-core中的columnVisibilityFeature提供并通过tableFeatures组合进表格实例。启用该 feature 后表格会获得专用的columnVisibility状态以及一组管理显隐的 API。import { columnVisibilityFeature, createTable, tableFeatures, } from tanstack/alpine-table const features tableFeatures({ columnVisibilityFeature }) const table createTable({ features, columns, get data() { return local.data }, })在 packages/table-core/src/features/column-visibility/columnVisibilityFeature.ts 中可以确认该 feature 通过getInitialState注入默认的columnVisibility状态通过assignColumnPrototype挂载列级 APIcolumn_getIsVisible、column_getCanHide、column_toggleVisibility、column_getToggleVisibilityHandler通过assignRowPrototype挂载行级 APIrow_getVisibleCells、row_getVisibleCellsByColumnId并通过constructTableAPIs挂载表级 APItable_getVisibleFlatColumns、table_getVisibleLeafColumns、table_setColumnVisibility、table_toggleAllColumnsVisible等。columnVisibility 状态语义columnVisibility是一个列 ID 到布尔值的映射对象。其语义遵循缺失即可见的约定列的 ID不在映射中或对应值为true列可见列的 ID在映射中且值为false列隐藏。对应实现见 columnVisibilityFeature.utils.ts 中的column_getIsVisible叶子列直接读取atoms.columnVisibility中自身 id 的值缺失时回退为true父级分组列则递归检查其子列只要存在任一可见子列即视为可见。因此columnVisibility状态只以叶子列 ID 为键对分组列做显隐操作时框架会展开到其全部可隐藏的叶子列见column_toggleVisibility的 leafColumns 遍历逻辑同文件。默认状态为空对象getDefaultColumnVisibilityState返回空 map即默认所有列可见。table_resetColumnVisibility可以恢复初始状态无参数时克隆initialState.columnVisibility传true则重置为空对象全部可见。三种状态所有权方案按谁拥有columnVisibility状态划分官方推荐三种做法适用场景不同。方案一外部 Atomv9 推荐最细粒度如果需要在表格之外拥有该状态例如持久化用户偏好、跨组件共享v9 推荐使用外部 atom 并通过atoms选项注入。tanstack/store本就是tanstack/alpine-table的依赖因此createAtom开箱即用。外部 atom 让应用中任何位置都能进行细粒度订阅其他代码读写可见性状态时无需经过持有表格的组件。import { createAtom } from tanstack/store import { columnVisibilityFeature, createTable, tableFeatures, } from tanstack/alpine-table import type { ColumnVisibilityState } from tanstack/alpine-table const features tableFeatures({ columnVisibilityFeature }) const columnVisibilityAtom createAtomColumnVisibilityState({ columnId1: true, columnId2: false, // 默认隐藏该列 columnId3: true, }) // 在任意需要的地方订阅 atom columnVisibilityAtom.subscribe(() { // 响应显隐变化 }) const table createTable({ features, //... atoms: { columnVisibility: columnVisibilityAtom, }, })源码侧可以验证 atom 是显隐 API 的数据源feature 的列级与表级方法均以table.atoms.columnVisibility?.get()作为 memo 依赖见 columnVisibilityFeature.tscolumn_getIsVisible也直接从该 atom 读取。通过columnVisibilityAtom.set(...)或update(...)写入新值时订阅方会收到通知并触发相关 memo 失效这正是细粒度订阅的底层机制。方案二Alpine.reactive 受控 slicev8 风格兼容v8 风格的state.columnVisibilityonColumnVisibilityChange组合依然受支持将 slice 放在Alpine.reactive对象中由你负责回写。该方案便于简单集成或迁移 v8 代码但粒度不如外部 atom 细。更深入的对比可参考 Table State Guide。const local Alpine.reactive({ columnVisibility: { columnId1: true, columnId2: false, // 默认隐藏该列 columnId3: true, } as ColumnVisibilityState, }) const table createTable({ features, //... state: { get columnVisibility() { return local.columnVisibility // 把响应式 slice 接回表格 }, //... }, onColumnVisibilityChange: (updater) { local.columnVisibility typeof updater function ? updater(local.columnVisibility) : updater }, })该方案依然有效是因为 feature 在getDefaultTableOptions中通过makeStateUpdater(columnVisibility, table)生成了默认的onColumnVisibilityChange见 columnVisibilityFeature.ts一旦你显式传入自己的 handler即可接管写入逻辑。方案三initialState 一次性初始化如果不需要在表格外部管理显隐状态直接通过initialState设置初始显隐即可之后由表格内部状态接管。[!NOTE] 如果columnVisibility同时出现在initialState与受控选项atoms或state中受控值优先initialState会被忽略。请只在其中一个位置提供columnVisibility。const features tableFeatures({ columnVisibilityFeature }) const table createTable({ features, //... initialState: { columnVisibility: { columnId1: true, columnId2: false, // 默认隐藏该列 columnId3: true, }, //... }, })在示例 examples/alpine/column-visibility/src/main.ts 中三种方案以注释形式并列给出initialState/atoms/stateonColumnVisibilityChange并配有enableHiding: false表格级禁用隐藏与debugTable: true开关可直接取消注释切换验证。禁止隐藏指定列默认所有列都可被隐藏。若要阻止某些列被隐藏为该列设置enableHiding: false。const columns [ { header: ID, accessorKey: id, enableHiding: false, // 禁用该列的隐藏能力 }, { header: Name, accessorKey: name, // 可以被隐藏 }, ]显隐判断同时受列级columnDef.enableHiding与表格级table.options.enableHiding约束两者默认值均为true任一为false即不可隐藏见 columnVisibilityFeature.utils.ts 的column_getCanHide。此外table_toggleAllColumnsVisible在全部隐藏时会将不可隐藏列的可见性写为true保证这些列始终可见同文件。列级显隐 API 与开关 UI以下列级方法专为渲染显隐开关设计见 columnVisibilityFeature.ts 中assignColumnPrototype的注册column.getCanHide()是否允许隐藏。适合用于禁用显隐开关例如enableHiding: false的列。column.getIsVisible()当前是否可见。适合设置开关的初始勾选状态。column.toggleVisibility(visible?)切换列可见性。省略参数时翻转当前状态显式传布尔值时直接写入。对分组列会递归应用到可隐藏的叶子列。column.getToggleVisibilityHandler()返回一个事件处理器读取event.target.checked并写入列可见性是toggleVisibility与 UI 事件之间的快捷接线。在 Alpine 模板中请将复选框渲染在真实 DOM 元素上而非x-html字符串内用:checked绑定column.getIsVisible()用:disabled绑定!column.getCanHide()并从change调用getToggleVisibilityHandler返回的处理器template x-forcolumn in table.getAllLeafColumns() :keycolumn.id label input typecheckbox :checkedcolumn.getIsVisible() :disabled!column.getCanHide() changecolumn.getToggleVisibilityHandler()($event) / span x-textcolumn.id/span /label /template全选/全不选开关则使用表级辅助方法table.getIsAllColumnsVisible()与table.getToggleAllColumnsVisibilityHandler()label input typecheckbox :checkedtable.getIsAllColumnsVisible() changetable.getToggleAllColumnsVisibilityHandler()($event) / Toggle All /label对应的完整界面实现在 examples/alpine/column-visibility/index.html左侧column-toggle-panel面板顶部是 Toggle All 复选框下方遍历table.getAllLeafColumns()为每个叶子列渲染独立开关。这些 handler 均以event.target.checked为数据源见column_getToggleVisibilityHandler与table_getToggleAllColumnsVisibilityHandlercolumnVisibilityFeature.utils.ts 与 同文件因此绑定的元素必须是真实输入控件。此外表级还提供以下编程式 API注册于 columnVisibilityFeature.tstable.setColumnVisibility(updater)接受新状态对象或(old) new更新函数通过onColumnVisibilityChange路由写入table.resetColumnVisibility(defaultState?)重置可见性table.toggleAllColumnsVisible(value?)显示/隐藏全部可隐藏列table.getIsSomeColumnsVisible()是否至少有一列可见适合实现三态全选控件。渲染可见性感知的表头与表体启用列显隐后一个常见误区是继续使用不考虑可见性的 API。以下 API不会把列显隐纳入计算table.getAllLeafColumns()、table.getAllFlatColumns()会返回隐藏列row.getAllCells()会返回隐藏列的单元格。应改用对应的可见性感知变体table.getVisibleLeafColumns()、table.getVisibleFlatColumns()仅返回当前可见的列实现见 columnVisibilityFeature.utils.tsrow.getVisibleCells()仅返回可见列的单元格且在启用列固定column pinning时按起始固定列 → 中间列 → 结尾固定列排序同文件row.getVisibleCellsByColumnId()以列 ID 为键的可见单元格查找表。表头分组 APItable.getHeaderGroups()、table.getFooterGroups()则已经内置了可见性感知无需额外处理。渲染单元格与表头内容时使用x-htmlFlexRender(...)迭代行模型时使用可见性感知 APItable thead template x-forheaderGroup in table.getHeaderGroups() :keyheaderGroup.id tr !-- 表头分组已自动考虑列可见性 -- template x-forheader in headerGroup.headers :keyheader.id th :colspanheader.colSpan template x-if!header.isPlaceholder span x-htmlFlexRender({ header })/span /template /th /template /tr /template /thead tbody template x-forrow in table.getRowModel().rows :keyrow.id tr !-- 使用可见性感知的单元格列表 -- template x-forcell in row.getVisibleCells() :keycell.id td x-htmlFlexRender({ cell })/td /template /tr /template /tbody /table上述模板与官方示例 examples/alpine/column-visibility/index.html 完全一致示例额外渲染了tfoot页脚同样基于table.getFooterGroups()其中header.isPlaceholder用于跳过分组占位单元格。FlexRender来自tanstack/alpine-table见 flexRender.ts负责把列定义中的header/cell/footer渲染函数输出为 HTML 字符串。由于columnVisibility的写入经由受控通道atom 或stateonColumnVisibilityChange回流row.getVisibleCells()等 API 的 memo 依赖中包含了table.atoms.columnVisibility见 columnVisibilityFeature.ts因此勾选开关后表体单元格会随之增删且 Alpine 的x-for依据:key高效复用 DOM。分组列场景下的显隐行为示例 examples/alpine/column-visibility/src/main.ts 定义了两级分组列结构Name 组含firstName/lastNameInfo 组含age与 More Info 子组。在分组结构下需要注意显隐状态只记录叶子列columnVisibility中不会出现分组列 ID对分组列调用toggleVisibility时框架会遍历其叶子列逐个写入见column_toggleVisibility的 leafColumns 循环分组列的getIsVisible由子列决定存在任一可见子列即为可见因此全隐藏后整个分组列也会从表头消失同时表头单元格的colSpan会自动适配剩余可见列。运行与验证示例通过 Vite 运行package.jsonexamples/alpine/column-visibility/package.json依赖tanstack/alpine-table、alpinejs与faker-js/faker并提供以下脚本pnpm install # 安装依赖 pnpm dev # 启动 Vite 开发服务器package.json scripts.dev pnpm build # 生产构建 pnpm test:types # tsc --noEmit 类型检查 pnpm test:e2e # Playwright 端到端测试仓库为该示例配有 Playwright 冒烟测试 examples/alpine/column-visibility/tests/e2e/smoke.spec.ts启动示例服务器、断言表格与表头可见、点击 Regenerate Data 后校验首行数据发生变化且页面无报错覆盖了表格渲染 数据响应式刷新的核心链路。运行环境为 Alpine.js Vite 的浏览器场景测试配置参考仓库根目录 playwright.config.ts。小结在tanstack/alpine-table中启用列显隐只需三步用tableFeatures({ columnVisibilityFeature })组合 feature、按需选择atoms推荐/stateonColumnVisibilityChange/initialState三种状态所有权方案之一、在模板中分别用可见性感知APIgetVisibleLeafColumns、getVisibleCells、getHeaderGroups渲染表头与表体。通过enableHiding保护关键列、通过列级与表级 toggle API 快速搭建显隐开关即可为 Alpine 应用交付完整的列显隐交互。【免费下载链接】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创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表