尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
TanStack Table Lit 快速上手:用 TableController 与 tableFeatures 构建 Web Components 表格
TanStack Table Lit 快速上手用 TableController 与 tableFeatures 构建 Web Components 表格【免费下载链接】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/tableTanStack Table 是一款 headless 表格库它负责管理表格的状态与逻辑排序、过滤、分页、行选择等而标记与样式 100% 由你掌控。本文基于仓库中的 Lit 快速上手文档带你从安装tanstack/lit-table到渲染出第一张 Lit 表格再逐步叠加排序等特性并深入源码剖析TableController、tableFeatures、FlexRender与状态选择器的工作原理。读完本文你将掌握在 Lit 自定义元素中集成 TanStack Table 的标准模式以及如何按需注册功能特性、组合可复用表格钩子。安装在项目中使用 Lit 表格适配器只需安装tanstack/lit-tablenpm install tanstack/lit-table该包由 packages/lit-table 提供它在tanstack/table-core之上构建并通过tanstack/lit-store接入 TanStack Store 的响应式系统。包的核心入口 packages/lit-table/src/index.ts 会重新导出 table-core 的全部内容并额外导出FlexRender、TableController、subscribe指令与createTableHook。第一张表格从零到可运行下面的组件是完整的把它粘贴进一个 Lit 应用就能看到一张可运行的表格。tanstack/lit-table适配器围绕TableController构建——它实现了 Lit 的ReactiveController只构造一次表格实例、让宿主订阅状态变化并在每次渲染时给你一个全新的表格实例。import { LitElement, html } from lit import { customElement, state } from lit/decorators.js import { repeat } from lit/directives/repeat.js import { FlexRender, TableController, tableFeatures } from tanstack/lit-table import type { ColumnDef } from tanstack/lit-table // 1. 定义数据形状 type Person { firstName: string lastName: string age: number } // 2. v9 新增声明该表格用到的特性这里暂未启用任何特性 const features tableFeatures({}) // 3. 定义列 const columns: ArrayColumnDeftypeof features, Person [ { accessorKey: firstName, // accessorKey 简写 header: First Name, cell: (info) info.getValue(), }, { accessorFn: (row) row.lastName, // accessorFn 替代方案需自定义 id id: lastName, header: () htmlspanLast Name/span, cell: (info) htmli${info.getValuestring()}/i, }, { accessorKey: age, header: () Age, }, ] customElement(person-table) export class PersonTable extends LitElement { // 4. 把数据放在响应式属性里 state() private data: ArrayPerson [ { firstName: tanner, lastName: linsley, age: 24 }, { firstName: tandy, lastName: miller, age: 40 }, { firstName: joe, lastName: dirte, age: 45 }, ] // 5. 为宿主元素创建一个 TableController private tableController new TableControllertypeof features, Person(this) protected render() { // 6. 在渲染过程中创建表格实例 const table this.tableController.table( { features, columns, data: this.data, }, () ({}), // 状态选择器未使用特性状态时传空即可 ) // 7. 用表格实例的 API 渲染标记 return html table thead ${repeat( table.getHeaderGroups(), (headerGroup) headerGroup.id, (headerGroup) html tr ${repeat( headerGroup.headers, (header) header.id, (header) html th ${header.isPlaceholder ? null : FlexRender({ header })} /th , )} /tr , )} /thead tbody ${repeat( table.getRowModel().rows, (row) row.id, (row) html tr ${repeat( row.getAllCells(), (cell) cell.id, (cell) htmltd${FlexRender({ cell })}/td, )} /tr , )} /tbody /table } }关于这段代码有几点值得注意tableFeatures({})声明了表格使用的可选特性。只注册需要的内容可以让打包体积更小并让 TypeScript 为表格实例推导出精确的类型。核心行模型core row model始终自动包含。特性行模型排序、过滤、分页在你需要时直接作为插槽注册到tableFeatures({...})调用上。FlexRender负责渲染列定义中的header、cell和footer无论它们是普通值还是 Lit 模板。如果你不想显式导入它也会以table.FlexRender的形式挂到实例上。tableController.table(...)的第二个参数是状态选择器它决定了table.state里包含什么在用到特性状态之前传一个空选择器完全没问题。查看完整的 Basic TableController 示例那里有带更多列和页脚的、可直接运行的版本。从源码理解 TableController 的渲染生命周期从源码看TableController的关键设计是一次构造、多次复用。packages/lit-table/src/TableController.ts 中的table()方法首次调用时会把coreReactivityFeature即litReactivity()与用户传入的features合并然后调用 table-core 的constructTable创建底层表格实例并用createRenderPhaseSource建立渲染期状态源this._table constructTable(mergedOptions) this._rootSource createRenderPhaseSourceTableStateTFeatures( this._table.store, shallow, ) this._setupSubscriptions()后续每次渲染调用table()时只做三件事通过table_setOptions暂存本轮 options真正的发布延迟到hostUpdated()、读取当前渲染快照、记录最新的状态选择器然后返回一个扩展了subscribe、FlexRender和只读state的LitTable实例。这也是为什么你可以在render()里反复调用它——它不会重复构造表格而是把新 options 合并进同一个实例。订阅门控逻辑体现在_setupSubscriptionsTableController.ts当传入选择器时只有所选状态发生浅比较变化才触发host.requestUpdate()不传选择器则保持每次状态变更都更新宿主的行为。配合hostUpdated()中调用markCommitted与table_publishExternalState外部可控状态会在 Lit 提交本轮渲染后被正确发布。litReactivity()本身定义在 packages/lit-table/src/reactivity.ts它基于tanstack/table-core/reactivity的renderPhaseReactivity并注入tanstack/lit-store的createAtom与batch让所有 atom 与用户提供的外部 atom 共享同一个 store 实例。叠加一个特性排序v9 中特性是可选加入opt-in的。要让列可排序需要在tableFeatures中注册rowSortingFeature与sortedRowModel工厂然后接上表头的点击处理器import { FlexRender, TableController, createSortedRowModel, rowSortingFeature, sortFns, tableFeatures, } from tanstack/lit-table const features tableFeatures({ rowSortingFeature, // 启用排序 API 与状态 sortedRowModel: createSortedRowModel(), // 客户端排序 sortFns, }) customElement(person-table) export class PersonTable extends LitElement { // data 与 tableController 与上文一致 protected render() { const table this.tableController.table( { features, columns, data: this.data, }, (state) ({ sorting: state.sorting }), // 选择排序状态 ) return html table thead ${repeat( table.getHeaderGroups(), (headerGroup) headerGroup.id, (headerGroup) html tr ${repeat( headerGroup.headers, (header) header.id, (header) html th ${ header.isPlaceholder ? null : htmldiv click${header.column.getToggleSortingHandler()} stylecursor: ${ header.column.getCanSort() ? pointer : default } ${FlexRender({ header })} ${ { asc: , desc: }[ header.column.getIsSorted() as string ] ?? null } /div } /th , )} /tr , )} /thead !-- tbody 与上文一致 -- /table } }现在点击表头会在升序、降序、不排序之间切换。其他所有特性都遵循同样的模式注册特性如果它带行模型工厂就把工厂作为插槽放到tableFeatures上然后使用它给表格、列和行新增的 API。关于自定义排序函数、多列排序与每列选项参见 Sorting Guide 和 Sorting 示例。特性注册的源码依据在 table-core 中rowSortingFeature、createSortedRowModel()、sortFns分别承担不同职责特性本身提供排序状态sorting、列上的getCanSort()/getToggleSortingHandler()/getIsSorted()等 API行模型工厂提供sortedRowModel这一排序后的行模型插槽sortFns则是内置的比较函数表。三者在tableFeatures({...})中被组装成完整的特性集并被ColumnDeftypeof features, Person用于类型推导——这就是为什么启用特性后表格实例上的 API 和类型会随之自动扩展。状态模型TanStack Store atom 与状态选择器v9 的表格状态由 TanStack Store 的 atom 支撑你通常不需要自己管理它设置起始值使用initialState调用特性 API 如table.setSorting(...)、table.nextPage()来修改状态当你的应用需要亲自拥有一段状态切片通过atoms选项或需要细粒度订阅时再深入阅读 Table State Guide——它是其余所有指南的基础。细粒度订阅subscribe 指令除了状态选择器TableController返回的LitTable还带有一个subscribe方法来自 packages/lit-table/src/subscribe-directive.ts它本质上是tanstack/lit-store的TanStackStoreSelector与 LitAsyncDirective的桥接。通过假的ReactiveControllerHost它把订阅回调接入指令的setValue()更新周期从而只重渲染被包裹的那一段模板// 1. 订阅特定状态切片仅当 rowSelection 变化时才重渲染 html div ${table.subscribe( table.store, (state) state.rowSelection, (rowSelection) htmlspanSelected: ${JSON.stringify(rowSelection)}/span, )} /div // 2. 订阅完整状态任何状态变更都会重渲染 html div ${table.subscribe( table.store, (state) htmlspanTotal rows: ${state.rowModel.rows.length}/span, )} /div 这种状态选择器控制宿主级更新、subscribe控制模板岛级更新的双层机制是 Lit 适配器在响应式更新性能上的核心设计宿主可以只对真正关心的状态切片做出反应其余内容交给模板内的细粒度订阅。FlexRender统一渲染列头、单元格与页脚FlexRender与底层的flexRender函数定义在 packages/lit-table/src/flexRender.tsflexRender(Comp, props)是最底层工具如果Comp是函数则调用它并传入 props否则原样返回适用于字符串、TemplateResult、DirectiveResult、Node等LitRenderable类型FlexRender({ header })/FlexRender({ cell })/FlexRender({ footer })是便捷封装一次只能传一个 prop内部自动调用flexRender(columnDef.cell, cell.getContext())等。值得一提的是FlexRender对分组聚合做了特判当单元格getIsAggregated()返回 true 时优先渲染aggregatedCell否则回退到普通cell当getIsPlaceholder()为 true 时返回null。这意味着表格分组grouping场景下聚合单元格无需额外样板代码。可组合表格createTableHook 一次定义、处处复用当应用里的多张表格共享特性、行模型与组件约定时可以用createTableHook一次性定义const features tableFeatures({ rowSortingFeature, sortedRowModel: createSortedRowModel(), sortFns, }) const { useAppTable, createAppColumnHelper } createTableHook({ features })然后在组件里直接调用useAppTable(this, { columns, data })而不是手动管理TableController。从 packages/lit-table/src/createTableHook.ts 的实现看createTableHook会创建基于lit/context的 table / cell / header 三个 context key返回预绑定特性与组件的createAppColumnHelper内部仍是 table-core 的createColumnHelper类型层面挂上绑定组件返回useAppTable——它在内部创建一个TableController和一个ContextProvider并把默认 options 与调用处 options 合并后者优先最终通过Object.assign(table, { AppCell, AppHeader, AppFooter, FlexRender, ...tableComponents })产出带App*包装函数与预绑定组件的扩展表格 API返回useTableContext/useCellContext/useHeaderContext供嵌套的子组件如分页控件、排序指示器、单元格组件通过lit/context消费最近的表格、单元格或表头实例。AppCell/AppHeader/AppFooter会把注册的cellComponents/headerComponents预绑定到对应实例上让列定义可以这样写columnHelper.accessor(age, { header: Age, cell: ({ cell }) cell.NumberCell(), // cell 上已预绑定 NumberCell 组件 })完整的模式包括预绑定的 cell/header 组件参见 Composable Tables Guide。下一步去哪里表格状态阅读 Table State Guide它是理解其余一切的基础指南。特性指南每个特性都有独立指南例如 Column Filtering、Pagination、Row Selection、Column Visibility以及 Sorting。可组合表格阅读 Composable Tables Guide掌握createTableHook的完整用法。示例浏览仓库中可运行的 Lit 示例集从 basic-table-controller 到各类特性演示直观了解端到端的预期用法特性对应的源码与测试位于 packages/lit-table/src 和 packages/lit-table/tests可对照验证 API 行为。【免费下载链接】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),仅供参考
RELATED

相关推荐

OpenFlux与gVisor版本兼容指南:版本选择与构建注意事项

OpenFlux与gVisor版本兼容指南:版本选择与构建注意事项

OpenFlux与gVisor版本兼容指南:版本选择与构建注意事项 【免费下载链接】OpenFlux Network stack research tool. TCP tunnel with pluggable transports. 项目地址: https://gitcode.com/GitHub_Trending/op/OpenFlux OpenFlux 是一款基于 Go 的网络协议栈研…

📅 2026/9/20 13:50:03
别找临时中转:用 TaoToken 做 Codex CLI 的兼容通道

别找临时中转:用 TaoToken 做 Codex CLI 的兼容通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/20 13:50:03
winget-cli 中 UndockedRegFreeWinRT 免注册 WinRT 的集成实践与源码剖析

winget-cli 中 UndockedRegFreeWinRT 免注册 WinRT 的集成实践与源码剖析

包管理器CLI 【免费下载链接】winget-cli WinGet is the Windows Package Manager. This project includes a CLI (Command Line Interface), PowerShell modules, and a COM (Component Object Model) API (Application Programming Interface). 项目地址: https:/…

📅 2026/9/20 13:50:03
MORE NEWS

更多资讯

📰

Enzyme ShallowWrapper.forEach() 详解:遍历浅渲染节点并链式操作

Enzyme ShallowWrapper.forEach() 详解:遍历浅渲染节点并链式操作 【免费下载链接】enzyme JavaScript Testing utilities for React 项目地址: https://gitcode.com/gh_mirrors/en/enzyme 导读 .forEach(fn) 是 Enzyme ShallowWrapper 提供的集合遍历方法&…

📰

Vue 3 组合式函数替代 Mixin:从底层原理到完整迁移实践

说实话,在 Vue 2 时代,Mixin 是我做逻辑复用的第一反应:两个组件都有分页逻辑,抽一个paginationMixin;两处都要发请求,抽一个requestMixin。用起来顺手,但项目一大人一多,Mixin 带来…

📰

独立开发与AI编程实战:从部署踩坑到性能优化月度复盘

1. 一月创作总览:从“随手写”到“内容闭环”时间过得太快,元旦的日历还没来得及换,一转眼2026年的第一个月就到底了。按照老规矩,月底写一篇月度文章汇总,既是对自己这个月内容产出的复盘,也给关注这个博客…

📰

7天掌握CSS 3D变形:透视、动画与面试实战

1. 为什么我建议前端小白学CSS 3D变形先讲个真实场景。我有一次在招聘现场看候选人做自我介绍,对方说自己是“两年前端经验”,简历上写满了Vue、React、小程序。我随手点开他带来的个人主页作品,平面卡片堆叠,没有任何空间层次&am…

📰

微信小程序性格测试开发全解析:从计分逻辑到支付v3对接

简介:这是一份性格心理测试微信小程序的完整源码压缩包,面向微信小程序开发者、心理学产品爱好者和计算机专业学生,可用于学习小程序前后端开发、界面搭建与交互设计。资源以“大五人格”等经典心理学理论为背景,用户完成测试后即…

📰

VLC 仓库 checkasm 测试编写完全指南:从 API 命名到汇编级验证与基准测试

音视频 【免费下载链接】vlc VLC media player - plays everything, runs anywhere. Code here: https://code.videolan.org/videolan/vlc 项目地址: https://gitcode.com/gh_mirrors/vl/vlc 点击查看 免费下载 本篇技术指南以 VLC 仓库 test/checkasm/ext/docs/wr…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬