- 前端
- UI组件
【免费下载链接】table
🤖 Headless UI for building powerful tables & datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table
导读
AppTableComponent是 TanStack Solid Table(@tanstack/solid-table)组合式表格 API 中的根级组件类型,它定义了<table.AppTable>这一“根包装组件”的签名:接收AppTableProps作为唯一入参,渲染并返回一个 SolidJS 的Element。本文从接口定义出发,结合packages/solid-table/src/createTableHook.tsx的源码实现与examples/solid/composable-tables完整示例,讲解AppTableComponent的类型签名、底层上下文提供机制,以及它在createTableHook组件化体系中的核心角色。读完本文,你将理解如何在 SolidJS 应用中以<table.AppTable>为根组件组织表头、单元格、表尾与工具栏组件,并利用useTableContext在任意注册组件中访问表格实例。
接口定义总览
AppTableComponent定义在 createTableHook.tsx,源码中的完整定义如下:
/** * Component type for AppTable - root wrapper with optional Subscribe */ export interface AppTableComponent<_TFeatures extends TableFeatures> { (props: AppTableProps): JSXElement }其对应的 API 参考文档位于 docs/framework/solid/reference/interfaces/AppTableComponent.md,文档将该接口定位为"Component type for AppTable - root wrapper with optional Subscribe"(AppTable 的组件类型——可选订阅的根包装器)。
类型参数_TFeatures
_TFeatures必须满足TableFeatures约束(源自@tanstack/table-core的 feature 类型体系)。- 该类型参数以下划线
_开头,说明它在类型层面仅用于约束与占位,运行时并不作为单独参数传递——真正承载特性集合的是createTableHook调用时传入的features配置。
函数签名
(props: AppTableProps): Element- 参数:
props,类型为AppTableProps。 - 返回值:
Element(SolidJS 的 JSX 元素)。
也就是说,AppTableComponent是一个标准 SolidJS 函数组件类型:凡是以(props: AppTableProps) => JSXElement形式实现的组件,都可作为table.AppTable的运行时形态。
唯一参数 AppTableProps:children
AppTableProps接口同样定义于 createTableHook.tsx:
export interface AppTableProps { children: JSXElement }该接口只有一个属性:
| 属性 | 类型 | 说明 |
|---|---|---|
children | JSXElement | 表格组件树的全部子内容,通常是<table>、工具栏、分页控件等 JSX 片段 |
由于根组件只负责提供上下文而不负责渲染具体内容,AppTableProps保持极简——所有视觉输出都来自children。这种设计让AppTable成为一个纯粹的“上下文容器”,与 SolidJS 的Context.Provider语义一一对应。
从源码看实现机制:上下文提供者
AppTableComponent类型对应的运行时实现是createAppTable内部定义的AppTable函数,见 createTableHook.tsx:
// AppTable - Root wrapper that provides table context function AppTable(props: AppTableProps): JSXElement { return ( <TableContext.Provider value={table}> {props.children} </TableContext.Provider> ) }核心机制一目了然:
createTableHook内部通过 SolidJS 的createContext创建TableContext(见 createTableHook.tsx),其泛型为SolidTable<TFeatures, any>,即创建表格时生成的扩展表实例。AppTable渲染时把createAppTable返回的table实例作为TableContext.Provider的value,再渲染props.children。- 因此,
<table.AppTable>之下的任意层级组件都能通过useTableContext()拿到同一个扩展表实例。
同时,文档注释中的 “optional Subscribe” 点出了它与 Solid 响应式的关系:createAppTable返回的table上挂载了Subscribe组件(定义于 createTable.ts),用于创建原子(atom)级响应式渲染边界;而AppTable本身不强制订阅,是否使用Subscribe由子组件按需决定——在 Solid 中,直接读取table.atoms.xxx.get()就会被原生依赖追踪,因此示例中常见的是在AppTable内部直接读取原子。
在 createTableHook 生态中的角色
AppTableComponent并非孤立接口,它是createTableHook组合式 API 家族的组成部分。createTableHook的函数注释将其定位为 TanStack Form 的createFormHook的表格等价物(见 createTableHook.tsx),允许开发者:
- 一次性定义 features、row models 与默认选项,供所有表格共享;
- 注册可复用的 table / cell / header 级组件;
- 通过 context 在组件中访问 table / cell / header 实例;
- 获得返回扩展表格的
createAppTable,以及预绑定的createAppColumnHelper。
createAppTable最终通过Object.assign将AppTable、AppCell、AppHeader、AppFooter、FlexRender以及全部tableComponents合并到 table 实例上(见 createTableHook.tsx):
return Object.assign(table, { AppTable, AppCell, AppHeader, AppFooter, FlexRender, ...tableComponents, }) as AppSolidTable<...>由此,table.AppTable的类型正是本文主角AppTableComponent<TFeatures>(见AppSolidTable类型定义,createTableHook.tsx)。同族的App*包装组件还包括:
| 组件 | 类型 | 职责 |
|---|---|---|
AppCell | AppCellComponent | 包装单元格,提供 cell 上下文并预绑定cellComponents与FlexRender |
AppHeader | AppHeaderComponent | 包装表头,提供 header 上下文并预绑定headerComponents |
AppFooter | AppHeaderComponent | 包装表尾,与 AppHeader 同型但使用FooterFlexRender |
FlexRender | typeof FlexRender | 便捷的 FlexRender 组件,渲染列定义中的 cell / header / footer 内容 |
配套的上下文读取钩子包括useTableContext、useCellContext、useHeaderContext,它们分别在未处于对应包装组件内时抛出明确错误(见 createTableHook.tsx),帮助开发者尽早发现组件放置错误。
实战:composable-tables 示例中的 AppTable 用法
仓库中的 examples/solid/composable-tables 示例完整展示了AppTableComponent的典型用法。首先在 hooks/table.ts 中通过createTableHook创建自定义钩子,注册三类组件:
export const { createAppColumnHelper, createAppTable, useTableContext, useCellContext, useHeaderContext, } = createTableHook({ features: tableFeatures({ columnFilteringFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortedRowModel: createSortedRowModel(), filteredRowModel: createFilteredRowModel(), paginatedRowModel: createPaginatedRowModel(), sortFns: { alphanumeric: sortFn_alphanumeric, text: sortFn_text }, filterFns: { includesString: filterFn_includesString, inNumberRange: filterFn_inNumberRange, }, }), getRowId: (row) => row.id, tableComponents: { PaginationControls, RowCount, TableToolbar }, cellComponents: { SelectCell, TextCell, NumberCell, StatusCell, ProgressCell, RowActionsCell, PriceCell, CategoryCell }, headerComponents: { SortIndicator, ColumnFilter, FooterColumnId, FooterSum }, })然后在 App.tsx 中,以<table.AppTable>作为整个表格组件树的根:
const table = createAppTable({ key: 'users-table', columns, get data() { return data() }, debugTable: true, enableRowSelection: true, }) return ( <table.AppTable> <table.TableToolbar title="Users Table" onRefresh={refreshData} onStressTest={stressTest} /> <table> <thead> <For each={table.getHeaderGroups()}> {(headerGroup) => ( <tr> <For each={headerGroup.headers}> {(h) => ( <table.AppHeader header={h}> {(header) => ( <th colSpan={header.colSpan} onClick={header.column.getToggleSortingHandler()}> <header.FlexRender /> <header.SortIndicator /> <header.ColumnFilter /> </th> )} </table.AppHeader> )} </For> </tr> )} </For> </thead> <tbody> <For each={table.getRowModel().rows}> {(row) => ( <tr> <For each={row.getAllCells()}> {(c) => ( <table.AppCell cell={c}> {(cell) => <td><cell.FlexRender /></td>} </table.AppCell> )} </For> </tr> )} </For> </tbody> {/* ... AppFooter、PaginationControls、RowCount ... */} </table> <table.PaginationControls /> <table.RowCount /> </table.AppTable> )该示例中两个表格(UsersTable与ProductsTable)共用同一套createAppTable钩子与注册组件,仅更换数据与列配置,充分验证了AppTable作为“一次注册、处处复用”根容器的价值。
组件内部如何拿到表格实例
注册的表格级组件通过useTableContext()获取上下文,例如 table-components.tsx 中的PaginationControls:
export function PaginationControls() { const table = useTableContext() const pagination = createMemo(() => table.atoms.pagination.get()) return ( <div class="pagination"> <button onClick={() => table.firstPage()} disabled={!table.getCanPreviousPage()}> {'<<'} </button> <button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}> {'<'} </button> {/* ... nextPage / lastPage / page size select ... */} </div> ) }同理,单元格级组件(如 cell-components.tsx 中的TextCell、NumberCell、StatusCell)通过useCellContext<TValue>()读取当前 cell 的取值并格式化渲染;表头/表尾级组件(SortIndicator、ColumnFilter、FooterSum等)通过useHeaderContext()读取 header。这些组件只要放在<table.AppTable>树内,就能在任意位置工作,这正是AppTableComponent作为根包装组件的意义所在。
使用注意与最佳实践
AppTable必须包住所有需要上下文的组件。useTableContext在找不到上下文时会抛出错误:'useTableContext' must be used within an AppTable component.(createTableHook.tsx),因此工具栏、分页、行统计等注册组件都应置于<table.AppTable>内。AppCell/AppHeader/AppFooter是AppTable的配套层级:它们分别提供 cell / header 上下文并预绑定注册组件,通常放在AppTable内部对应的<td>/<th>位置。- 列定义必须使用
createAppColumnHelper而非createColumnHelper:示例源码中的注释明确指出,使用<cell.TextCell />这类预绑定组件时,必须用createAppColumnHelper创建列定义(见 App.tsx),否则 cell / header / footer 上下文不会携带注册组件类型。 - 响应式边界按需选择:在 Solid 中,组件内直接调用
table.atoms.sorting.get()会被原生依赖追踪;当需要将原子读取显式隔离为独立渲染边界时,再使用table.Subscribe。AppTable本身对订阅保持开放(“optional Subscribe”),不强制任何模式。 TData自动推断:createAppTable的TData由data选项推断(createTableHook.tsx),而TFeatures已在createTableHook调用时绑定,因此业务组件无需重复书写泛型参数。
延伸阅读
- 接口参考:AppTableComponent 与 AppTableProps
- 核心源码:createTableHook.tsx(含
createTableHook、createAppTable、useTableContext的完整实现与 JSDoc 示例) - 基础表格实例:createTable.ts(
SolidTable类型与Subscribe的定义) - 完整示例:examples/solid/composable-tables/src/App.tsx、hooks/table.ts、components/table-components.tsx、components/cell-components.tsx
- 包入口:packages/solid-table/src/index.tsx
- 前端
- UI组件
【免费下载链接】table
🤖 Headless UI for building powerful tables & datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table
相关推荐
Preact Table AppTableComponent 接口解析:构建带可选 Subscribe 的表格根组件
Preact Table AppTableComponent 接口解析:构建带可选 Subscribe 的表格根组件 导读 AppTableComponent
前端UI组件Solid-Table 的 createTableHook 返回值全解析:CreateTableHookResult 接口与可组合表格架构
Solid Table 的 createTableHook 返回值全解析:CreateTableHookResult 接口与可组合表格架构 CreateTabl
前端UI组件TanStack Solid Table 可组合表格实战:用 createTableHook 构建共享特性与可复用组件的高阶表格工厂
TanStack Solid Table 可组合表格实战:用 createTableHook 构建共享特性与可复用组件的高阶表格工厂 导读 在大型 SolidJ
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考