尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

@tanstack/solid-table 参考指南:createTable、createTableHook 与 FlexRender 完整 API 详解

@tanstack/solid-table 参考指南:createTable、createTableHook 与 FlexRender 完整 API 详解 tanstack/solid-table 参考指南createTable、createTableHook 与 FlexRender 完整 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本文是基于 TanStack Table 仓库中docs/framework/solid/reference/index.mdAPI 参考索引编写的技术指南。它系统梳理tanstack/solid-table包的接口Interface、类型别名Type Alias与函数Function全集并结合包内源码createTable.ts、createTableHook.tsx、FlexRender.tsx、reactivity.ts与官方示例basic-use-table深入讲解其内部原理与实战用法。读完本文你将掌握如何用createTable创建 Solid 响应式表格实例、如何通过createTableHook搭建带预绑定组件的可组合表格体系以及如何用FlexRender渲染表头、单元格与表尾。一、包定位与 API 总览tanstack/solid-table是 TanStack Table 的 Solid 适配层核心思路是框架无关的表格内核tanstack/table-core Solid 响应式绑定。它把 table-core 的 Store atom 桥接到 Solid 的 signal/memo 上使得表格 API 与 atom 读取参与 Solid 依赖追踪——读取某个切片的计算只会更新相关 UI而不会失效无关部分。包入口 index.tsx 直接 re-export 了tanstack/table-core的全部内容以及本包的createTable、FlexRender、createTableHook。参考索引将其公开 API 划分为三类接口InterfacesAppCellComponent、AppCellProps、AppHeaderComponent、AppHeaderProps、AppTableComponent、AppTableProps、CreateTableHookResult。类型别名Type AliasesAppCellContext、AppColumnDefBase、AppColumnDefTemplate、AppColumnHelper、AppDisplayColumnDef、AppGroupColumnDef、AppHeaderContext、AppSolidTable、ComponentType、CreateTableHookOptions、FlexRenderProps、SolidTable。函数FunctionscreateTable、createTableHook、flexRender、FlexRender。其中App*前缀的类型全部由createTableHook机制产生是 Solid 适配层最具特色的部分。下面按“基础用法 → 组合增强 → 渲染工具 → 响应式底层”的顺序逐一展开。二、createTable创建 Solid 响应式表格实例2.1 函数签名function createTableTFeatures, TData(tableOptions): SolidTableTFeatures, TData;类型参数TFeatures extends TableFeatures要启用的表格特性集合featuresTData extends RowData行数据类型。参数tableOptions为TableOptionsTFeatures, TData返回类型是SolidTableTFeatures, TData——即 table-core 的TableTFeatures, TData与两个附加成员的交叉类型定义于 createTable.tsSubscribe创建“atom 追踪渲染边界”的组件。其children函数会读取所需的表格 atomSolid 只追踪这些 atom 读取实现切片级精确更新FlexRender挂在表实例上的便捷渲染组件等价于createTableHook的createAppTable暴露的table.FlexRenderAPI。2.2 源码层面的实现原理createTable的实现位于 createTable.ts关键流程如下获取响应式宿主const owner getOwner()!捕获当前 Solid 执行上下文的所有者再调用solidReactivity(owner)创建 reactivity 绑定合并选项用 Solid 的mergeProps将调用方传入的features与coreReactivityFeaturereactivity 绑定本身作为一个核心 feature合并再注入默认的mergeOptions实现构造表格调用constructTable(resolvedOptions)来自 table-core构建表格实例响应式同步选项createComputed中读取tableOptions.state中每个 key建立依赖随后在untrack中调用table.setOptions合并最新选项——这样外部状态变化会触发计算重跑但选项更新本身不产生额外追踪清理onCleanup(() reactivity.unmount?.())在组件卸载时统一退订所有 atom 订阅挂载扩展成员将Subscribe与FlexRender挂到表实例上后返回。2.3 最小实战示例参考官方示例 basic-use-table一个不启用任何额外特性的基础表格import { FlexRender, createColumnHelper, createTable, tableFeatures } from tanstack/solid-table import { For, createSignal } from solid-js type Person { firstName: string; lastName: string; age: number } // 1. 声明特性集合V9 起为必填项利于 tree-shaking const features tableFeatures({}) // 2. 用列助手定义列 const columnHelper createColumnHelpertypeof features, Person() const columns columnHelper.columns([ columnHelper.accessor(firstName, { header: First Name, cell: (info) info.getValue() }), columnHelper.accessor((row) row.lastName, { id: lastName, header: () spanLast Name/span, cell: (info) i{info.getValue()}/i, }), ]) function App() { const [data] createSignal([...defaultData]) // 3. 创建表实例features、columns、data 为必填 const table createTable({ key: basic-use-table, // 供 devtools 使用 debugTable: true, features, columns, get data() { return data() // getter 形式接入响应式数据源 }, }) // 4. 渲染表头 / 表体 / 表尾统一用 FlexRender return ( table thead For each{table.getHeaderGroups()} {(headerGroup) ( tr For each{headerGroup.headers} {(header) ( th{header.isPlaceholder ? null : FlexRender header{header} /}/th )} /For /tr )} /For /thead tbody For each{table.getRowModel().rows} {(row) ( tr For each{row.getAllCells()} {(cell) tdFlexRender cell{cell} //td} /For /tr )} /For /tbody tfoot For each{table.getFooterGroups()} {(footerGroup) ( tr For each{footerGroup.headers} {(header) ( th{header.isPlaceholder ? null : FlexRender footer{header} /}/th )} /For /tr )} /For /tfoot /table ) }提示tableFeatures({})是创建可共享TFeatures对象/类型的工具函数createColumnHelpertypeof features, Person()则把特性类型与行类型绑定进列定义保证列回调中的getValue()返回值类型安全。启用分页、排序、过滤等能力时只需在tableFeatures({ ... })中传入对应 feature 与 row model见 createTableHook.tsx 中的rowPaginationFeature、rowSortingFeature、columnFilteringFeature等。三、createTableHook带预绑定组件的组合式表格工厂createTableHook是 Solid 适配层的“组合增强”入口官方将其定位为 TanStack Form 中createFormHook的表格对应物见 createTableHook.tsx。3.1 函数签名function createTableHookTFeatures, TTableComponents, TCellComponents, THeaderComponents( __namedParameters ): CreateTableHookResultTFeatures, TTableComponents, TCellComponents, THeaderComponents;四个类型参数分别约束特性集合TFeatures extends TableFeatures、表级组件集合Recordstring, ComponentTypeany、单元格级组件集合与表头级组件集合。入口参数类型为CreateTableHookOptionsTFeatures, TTableComponents, TCellComponents, THeaderComponents它是TableOptions剔除columns | data | store | state | initialState后的剩余项再叠加三个可选的组件注册字段createTableHook.tsxtableComponents?需要访问表实例的组件如{ PaginationControls, GlobalFilter, RowCount }组件内部用useTableContext()取表cellComponents?需要访问单元格实例的组件如{ TextCell, NumberCell, DateCell, CurrencyCell }用useCellContext()取单元格headerComponents?需要访问表头实例的组件如{ SortIndicator, ColumnFilter, ResizeHandle }用useHeaderContext()取表头。3.2 返回值CreateTableHookResultCreateTableHookResultcreateTableHook.tsx暴露六项能力appFeatures传入的TFeatures特性对象createAppColumnHelper预绑定TFeatures与已注册组件的列助手返回AppColumnHelperTDatacreateAppTable创建“增强表格”的 hookTData从data选项自动推断返回AppSolidTable即SolidTable叠加AppTable/AppCell/AppHeader/AppFooter/FlexRender以及全部tableComponentsuseTableContext读取最近table.AppTable提供的增强表实例useCellContext读取最近table.AppCell提供的单元格实例已扩展cellComponents与上下文绑定的FlexRenderuseHeaderContext读取最近table.AppHeader/table.AppFooter提供的表头实例已扩展headerComponents与上下文绑定的FlexRender。三个use*Context都有明确的越界保护在对应App*包装组件之外调用会抛出带修复建议的错误如useTableContext must be used within an AppTable component. ...见 createTableHook.tsx。3.3 完整组合示例以下为 createTableHook.tsx 中官方示例的完整结构// hooks/table.ts —— 一次性定义特性、行模型与默认选项所有表格共享 export const { createAppTable, createAppColumnHelper, useTableContext, useCellContext, useHeaderContext, } createTableHook({ features: tableFeatures({ rowPaginationFeature, rowSortingFeature, columnFilteringFeature, paginatedRowModel: createPaginatedRowModel(), sortedRowModel: createSortedRowModel(), filteredRowModel: createFilteredRowModel(), sortFns, filterFns, }), tableComponents: { PaginationControls, RowCount }, cellComponents: { TextCell, NumberCell }, headerComponents: { SortIndicator, ColumnFilter }, }) // 列助手已绑定 TFeatures 与组件类型 const columnHelper createAppColumnHelperPerson() // 表级组件通过 useTableContext 取表实例 function PaginationControls() { const table useTableContext() // TFeatures 已确定 return ( table.Subscribe {(atoms) ( div button onClick{() table.previousPage()}Prev/button spanPage {atoms.pagination.get().pageIndex 1}/span button onClick{() table.nextPage()}Next/button /div )} /table.Subscribe ) } // 业务表格TData 从 data 推断 function UsersTable({ data }: { data: Person[] }) { const table createAppTable({ columns, data }) return ( table.AppTable table thead For each{table.getHeaderGroups()} {(headerGroup) ( tr For each{headerGroup.headers} {(h) ( table.AppHeader header{h} {(header) ( th header.FlexRender / header.SortIndicator / /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) tdcell.TextCell //td} /table.AppCell )} /For /tr )} /For /tbody /table table.PaginationControls / /table.AppTable ) }3.4 内部实现要点从源码看createTableHook的“增强”机制依赖三个内部 Solid ContextcreateTableHook.tsxTableContext、CellContext、HeaderContext。createAppTable先用mergeProps(defaultTableOptions, tableOptions)合并默认选项调用处传入的选项优先再调用createTable构建实例AppTable是TableContext.Provider根包装组件AppCell/AppHeader/AppFooter通过Object.assign(props.cell, { FlexRender: CellFlexRender, ...cellComponents })把组件与上下文绑定的FlexRender直接“预绑定”到实例对象上createTableHook.tsx同时向 Context 提供原始实例——这就是为什么列定义里能直接写cell.TextCell /、header.SortIndicator /createAppColumnHelper运行时复用 table-core 的createColumnHelper差异只在类型层AppColumnHelper的accessor/display/group/columns方法签名里cell/header/footer的渲染上下文都被替换为包含预绑定组件的AppCellContext/AppHeaderContext见 createTableHook.tsx。由此带来的收益特性、行模型、默认选项只定义一次组件注册一次类型系统自动让“组件是否可用”在编译期被感知这正是该 API 组合能力的核心价值。四、FlexRender 与 flexRender渲染层核心工具4.1 flexRender 函数function flexRenderTProps(Comp, props): Element;定义于 FlexRender.tsx。它接受一个“模板值”可以是函数组件或 JSX 元素和上下文 propsnull/undefined直接返回null函数则通过createComponent(Comp, props)创建组件实例其余情况原样返回。适用于需要底层函数形态的场景flexRender(cell.column.columnDef.cell, cell.getContext())4.2 FlexRender 组件FlexRender cell{cell} / FlexRender header{header} / FlexRender footer{footer} /组件版签名见FlexRenderProps类型别名它使用联合类型约束三个 prop 只能传一个cell/header/footer互斥其余必须为undefined从类型层面杜绝误用FlexRender.tsx。实现上FlexRender.tsx通过SwitchMatch keyed分发keyed是刻意为之保证当 prop 换成新的 cell/header 实例例如虚拟滚动场景下同位置出现新数据时内容强制重渲染非 keyed 的Match只在真值变化时重跑 children。对 cell 的渲染还内置了对分组grouping特性的兼容逻辑当注册了分组特性时单元格可能处于三种特殊模式——aggregated聚合渲染columnDef.aggregatedCell未定义时回退到columnDef.cellplaceholder占位组内重复值渲染nullgrouped分组头回退到columnDef.cell需要自定义分组头时消费者通常先自行分支cell.getIsGrouped()。代码通过可选链getIsAggregated?.()保证未注册分组特性时依然安全FlexRender.tsx。五、类型系统App 系列别名与列定义createTableHook的增强类型体系均定义于 createTableHook.tsxComponentTypeT extends Recordstring, anyComponentT的简写统一组件签名AppColumnDefTemplateTPropsstring | ((props: TProps) any)列定义中cell/header/footer的模板类型AppCellContext/AppHeaderContext增强后的渲染上下文cell/header上直接带有注册组件与FlexRender同时保留column、row、table、getValue、renderValue等标准字段AppColumnDefBase/AppDisplayColumnDef/AppGroupColumnDef分别对应数据列、展示列、分组列的增强列定义Omit掉标准cell/header/footer后替换为增强模板类型其中AppGroupColumnDef.columns保留嵌套子列AppColumnHelperaccessor按 key 或函数取数自动推断TValue、columns包装数组以保留每列各自的TValue类型、display非数据列、group分组列四个方法AppSolidTableSolidTable叠加AppTable/AppCell/AppHeader/AppFooter/FlexRender与tableComponents的完整增强表类型createTableHook.tsxAppTableComponent即其根包装组件类型createTableHook.tsx。配合useTableContextTData()、useCellContextTValue()、useHeaderContextTValue()的泛型参数业务代码可以在组件内部获得完全类型化的实例访问。六、响应式底层reactivity 与 Subscribe 渲染边界Solid 适配层的响应式桥接实现在 reactivity.tssignalToReadonlyAtom/signalToWritableAtom把 Solid 的createMemo/createSignal包装成 TanStack Store 的ReadonlyAtom/Atom补齐get()、set()、subscribe()接口——subscribe用runWithOwner(owner, ...)在表格创建者的 owner 下运行确保订阅依赖归属正确reactivity.tscreateReadonlyAtom用createMemo包装派生值支持compareequals与debugName选项createWritableAtom用createSignal包装可写状态schedule: (fn) queueMicrotask(() fn())调度策略基于微任务batch透传 Solid 的batch用于批量原子更新unmount统一退订所有 Store 订阅供createTable的onCleanup调用。结合createTable源码可知表格状态的 atom 由 TanStack Store 提供而 options 存储保持框架原生行模型 API 在渲染时直接读取table.options。table.Subscribe则是把这些 atom 读取收敛为 Solid 可追踪边界的关键组件——children(atoms)里atoms.pagination.get()之类的读取会被 Solid 记录依赖数据切片变化时只重渲染相关子树实现细粒度的性能控制。七、完整参考索引速查以下为 reference/index.md 中全部公开 API 的官方文档链接接口AppCellComponentAppCell 组件类型AppCellPropsAppHeaderComponentAppHeader/AppFooter 组件类型AppHeaderPropsAppTableComponentAppTable 根包装组件可选用 SubscribeAppTablePropsCreateTableHookResult类型别名AppCellContext、AppHeaderContextAppColumnDefBase、AppColumnDefTemplate、AppDisplayColumnDef、AppGroupColumnDefAppColumnHelperAppSolidTable、SolidTableComponentTypeCreateTableHookOptionsFlexRenderProps函数createTablecreateTableHookflexRender 与 FlexRender八、进一步探索源码入口包导出见 packages/solid-table/src/index.tsx静态函数透传见 static-functions.ts完整示例本仓库examples/solid/目录下提供了basic-use-table、basic-app-table、composable-tables、kitchen-sink、virtualized-rows、spreadsheet、with-tanstack-form、with-tanstack-query等覆盖不同特性的可运行示例其中 basic-use-table 演示createTable基础用法特性组合参考tableFeatures与各 row model 的装配方式见 createTableHook.tsx 的示例配置底层内核Table、TableOptions、TableFeatures等类型的定义位于tanstack/table-corepackages/table-core/srcTableReactivityBindings契约位于 packages/table-core/src/reactivity.ts。按上述 API 组合你可以从“单个createTable的基础表格”平滑演进到“createTableHook驱动的多表格共享特性与组件的应用体系”在享受 Solid 细粒度响应式更新的同时获得完整的 TypeScript 类型推导保障。【免费下载链接】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),仅供参考
返回列表