
前端UI组件【免费下载链接】gridstack.jsBuild interactive dashboards in minutes.项目地址https://gitcode.com/gh_mirrors/gr/gridstack.js点击查看免费下载本指南以 gridstack.js React 封装层的类型扩展文档 react/doc/api/types.md 为核心骨架系统讲解 React 侧独有的GridStackWidget、GridStackOptions、GridStackNode、GridStackHostApi以及 DOM 回引用类型。你将掌握组件化仪表盘的 JSON 数据模型、序列化/反序列化扩展点、惰性渲染与嵌套网格的类型写法并理解这些类型如何与 gridstack.tsx、gridstack-item.tsx、registry.ts 中的实际实现一一对应。一、类型体系总览React 封装层如何扩展核心类型gridstack.js 的核心类型如GridStackWidget、GridStackOptions定义在核心模块 src/types.ts 中React 封装层则通过接口继承 Omit 类型裁剪的方式在 react/projects/lib/src/types.ts 中声明扩展保持同一个标识符、在 React 入口下增强的约定import type { GridStackOptions as CoreGridStackOptions, GridStackWidget as CoreGridStackWidget, GridStackNode as CoreGridStackNode, GridHTMLElement as CoreGridHTMLElement, GridItemHTMLElement as CoreGridItemHTMLElement, } from gridstack;React、Vue、Angular 三个框架封装层统一采用component/props字段名描述组件化 widget JSON见 types.ts 顶部注释因此这套类型系统对理解整个框架封装族的 widget 数据模型都有参考价值。按 types.md 的目录结构React 类型系统包含 6 个接口、1 个类型别名类型作用GridStackHostApi挂在grid-stackDOM 元素上的宿主管道_gridComp用于addRemoveCB回调分发GridStackWidgetReact 版的 widget 创建/序列化数据模型比核心版多了component/props等字段GridStackNodeReact 版的运行时节点描述追加component字段GridStackOptionsReact 版的网格配置children与subGridOpts递归使用 React 扩展后的 widget 类型GridHTMLElement网格 DOM 元素的类型增强追加_gridComp宿主管道GridItemHTMLElementwidget DOM 元素类型增强追加_gridItemRef回引用与_lazyObserverGridStackWidgetProps类型别名等价于Recordstring, unknown二、GridStackWidgetReact 组件化 widget 数据模型2.1 定义与继承关系GridStackWidget是 React 封装层最核心的数据类型它在 types.ts 第 32 行定义通过OmitCoreGridStackWidget, subGridOpts继承核心类型裁剪掉核心版subGridOpts换成 React 版递归类型核心版GridStackWidget见 doc/API.mdexport interface GridStackWidget extends OmitCoreGridStackWidget, subGridOpts { component?: string; props?: GridStackWidgetProps; class?: string; el?: HTMLElement; subGridOpts?: GridStackOptions; lazyLoad?: boolean; }2.2 扩展字段逐个解析字段类型说明component?string传入GridStack components{...} /的组件映射表ComponentMap中的键名用于把 widget JSON 渲染成对应 React 组件props?GridStackWidgetProps传给该组件的 props类型为Recordstring, unknownclass?stringwidget 根元素上的额外 CSS 类名与 Angular 版 widget JSON 中的class字段对应el?HTMLElement通过addRemoveCB移除 widget 时的运行时 DOM 节点不会被序列化subGridOpts?GridStackOptions嵌套网格配置递归类型使用 React 扩展后的 widget childrenlazyLoad?boolean延迟渲染widget 滚动进入视口后才渲染组件与 Angular 版 lazyLoad 对应其中props的类型别名GridStackWidgetProps定义在第 30 行export type GridStackWidgetProps Recordstring, unknown;该设计意味着 props 完全开放任意可序列化的 JSON 数据都可以作为组件入参——这正是组件模式component mode下 widget 声明式写法的基础。2.3 实战组件模式下的 widget JSON结合 react/README.md 的用法一个典型用法是直接在GridStackOptions.children中声明componentpropsimport { GridStackOptions } from gridstack; import { GridStack } from gridstack/dist/react; function Text({ text }: { text: string }) { return div{text}/div; } const options: GridStackOptions { column: 12, cellHeight: 50, children: [ { id: a, x: 0, y: 0, w: 2, h: 2, component: Text, props: { text: Hello } }, ], }; export function Board() { return GridStack options{options} components{{ Text }} /; }底层渲染链路为GridStack.init触发addRemoveCB→ registry.ts 的gsCreateReactComponents创建.grid-stack-item元素并写入_gridItemRef→ 调用gridHost.registerSyntheticItemId(id)→ 主组件 gridstack.tsx 的syntheticItems分支按node.component查表渲染GridStackItem门户portal把Comp {...props} /挂载进.grid-stack-item-content。其中class字段会被拆分成类名追加到 item 元素上registry.ts 第 61-63 行。2.4 序列化时 component/props 的写入GridStack.save()依赖核心的GridStack.saveCB钩子React 封装层通过 registry.ts 的gsSaveAdditionalReactInfo把节点上的component、props拷回序列化结果并剥离纯运行时字段export function gsSaveAdditionalReactInfo(node: GridStackNode, w: GridStackWidget): void { const n node as GridStackNode { component?: string; props?: Recordstring, unknown }; if (n.component ! null) w.component n.component; if (n.props ! null) w.props { ...n.props }; delete (w as Recordstring, unknown).visibleObservable; // ... }三、GridStackOptionsReact 版网格配置GridStackOptionstypes.ts 第 50 行通过OmitCoreGridStackOptions, children | subGridOpts继承核心配置核心版完整配置项见 doc/API.md列数、cellHeight、拖拽/缩放约束、responsive 等均继承自核心类型React 层不改写export interface GridStackOptions extends OmitCoreGridStackOptions, children | subGridOpts { children?: GridStackWidget[]; subGridOpts?: GridStackOptions; lazyLoad?: boolean; }React 层新增/覆盖的三个字段字段类型说明children?GridStackWidget[]网格初始化的 widget 列表元素为 React 版GridStackWidgetsubGridOpts?GridStackOptions嵌套网格配置递归使用 React 版类型与 widget 层级的subGridOpts配合实现嵌套子网格lazyLoad?boolean延迟渲染所有item 组件直到其滚动进视口单个 widget 上的lazyLoad优先覆盖此全局设置lazyLoad的优先级语义在文档中明确为Per-itemlazyLoadoverrides即全局开关是兜底逐项开关优先。实现上registry.ts 第 78 行调用核心工具Utils.lazyLoad(w)来按正确优先级求值命中懒加载时给 item 元素挂IntersectionObserver_lazyObserver进入视口后调用gridHost.registerSyntheticItemId(id)才真正渲染 React 组件const lazy Utils.lazyLoad(w); if (lazy) { el._lazyObserver new IntersectionObserver(([entry]) { if (entry.isIntersecting) { el._lazyObserver?.disconnect(); delete el._lazyObserver; gridHost.registerSyntheticItemId(id); } }); setTimeout(() el._lazyObserver?.observe(el)); // 等 GS 设置好定位属性后再观察 } else { gridHost.registerSyntheticItemId(id); }当 widget 被移除时gsCreateReactComponents的移除分支会先disconnect()观察器并清理_lazyObserver避免泄漏。3.1 嵌套子网格的类型写法由于subGridOpts递归引用 React 版GridStackOptions嵌套子网格中的children同样支持component/propsconst options: GridStackOptions { column: 12, children: [ { id: parent, x: 0, y: 0, w: 6, h: 4, subGridOpts: { column: 6, children: [ { id: c1, x: 0, y: 0, w: 3, h: 2, component: Text, props: { text: nested } }, ], }, }, ], };嵌套子网格使用父级GridStack传入的同一份components映射表见 react/README.md 的 Nested subgrids 一节。创建子网格时registry.ts 的gsCreateReactComponents会为isGrid分支创建.grid-stack子容器并通过nearestGridComp(parent)向上查找、继承宿主_gridComp确保子网格内的 widget 也能注册门户渲染。四、GridStackNode 与 DOM 回引用类型4.1 GridStackNode运行时节点GridStackNodetypes.ts 第 46 行直接继承核心版GridStackNode核心版定义于 doc/API.md包含el指向 DOM 元素、grid指向所属网格实例、subGrid实际子网格实例、visibleObservable可见性懒加载观察器等运行时字段React 层仅追加一个字段export interface GridStackNode extends CoreGridStackNode { component?: string; }component是运行时节点上的组件键名。注意核心版GridStackNode继承自核心GridStackWidget因此节点的props等字段也随节点可用React 的事件回调如onChange拿到的节点可以直接读取component判断组件类型。4.2 GridHTMLElement网格元素的宿主管道GridHTMLElement第 57 行扩展核心的GridHTMLElement追加export interface GridHTMLElement extends CoreGridHTMLElement { _gridComp?: GridStackHostApi; }_gridComp是类型文档中GridStackHostApi的承载位置。在 gridstack.tsx 的初始化useLayoutEffect中网格根元素被盖上el._gridComp hostApiRef.current销毁时delete el._gridComp。核心的addRemoveCB/saveCB/updateCB回调由此通过 DOM 回引用找到宿主不依赖任何对单网格状态的闭包这正是 registry 的静态回调设计前提与 Angular 的gsCreateNgComponents同模式。4.3 GridItemHTMLElementwidget 元素的双回引用GridItemHTMLElement第 61 行扩展核心的GridItemHTMLElement追加两个字段export interface GridItemHTMLElement extends CoreGridItemHTMLElement { _gridItemRef?: { id: string; gridComp: GridStackHostApi }; _lazyObserver?: IntersectionObserver; }字段说明_gridItemRef{ id, gridComp }二元组id是 widget 的标识portal 渲染的 keygridComp指向所属网格的宿主管道供移除时反注册_lazyObserver懒加载 widget 的 IntersectionObserveritem 被移除时清理_gridItemRef由gsCreateReactComponents写入registry.ts 第 74 行移除时读取并调用gridComp.unregisterSyntheticItemId(id)后删除回引用。五、GridStackHostApiReact 与 GridStack 引擎之间的宿主管道GridStackHostApi是文档中最内部的接口它被盖章在grid-stack元素上_gridComp供核心引擎的addRemoveCB等回调反向调用 React 宿主。完整签名如下types.ts 第 14-28 行export interface GridStackHostApi { registerSyntheticItemId(id: string): void; unregisterSyntheticItemId(id: string): void; requestUpdate(): void; registerWidgetSerializer: ( id: string, serialize: () Recordstring, unknown | undefined, deserialize?: (data: Recordstring, unknown) void ) () void; mergeWidgetPropsForSave(id: string, w: GridStackWidget): void; deserializeWidget(id: string, w: GridStackWidget): void; }5.1 五个方法的职责与实现方法职责对应实现gridstack.tsxregisterSyntheticItemId(id)注册合成 widget如从侧边栏拖入、无 id 的 widget由 registry 临时铸造gs-react-N序列号 id触发 React 渲染对应组件门户第 107-115 行同时会取消同 id 的待删除标记跨网格 DnD 场景unregisterSyntheticItemId(id)反注册合成 widget卸载门户第 117-133 行删除延迟一个微任务执行若同一同步块内registerSyntheticItemId再次触发跨网格 DnD 先 remove 后 add则取消删除、React 子树不被卸载requestUpdate()通知 React 在 GSupdate()/updateCB之后重新读取节点 props内部委托bumpLayout递增layoutVersion触发重渲染registerWidgetSerializer(id, serialize, deserialize?)注册/注销 widget 的序列化与反序列化回调返回注销函数第 135-149 行存入serializersRef/deserializersRef两个 MapmergeWidgetPropsForSave(id, w)在grid.save()期间把useWidgetSerializer的serialize()结果合并进w.props第 151-154 行w.props { ...(w.props ?? {}), ...extra }deserializeWidget(id, w)在 GSupdateCB之后调用已注册的 deserialize 函数让组件响应更新后的 props第 156-158 行5.2 稳定身份设计callbacksRef hostApiRef一个值得注意的实现细节hostApiRef在组件挂载时只创建一次但其方法内部全部委托给callbacksRef.current每次渲染都会刷新为最新闭包从而保证_gridComp对象身份永远稳定同时所有调用者拿到的始终是最新闭包gridstack.tsx 第 160-186 行。这解释了为什么静态回调registry通过 DOM 回引用调用的宿主管道可以安全地长期持有。5.3 useWidgetSerializer 与 Host API 的联动开发者一般不直接调用 Host API而是通过 hooks.ts 暴露的useWidgetSerializer钩子在组件内部注册。该钩子从GridStackWidgetContext读取registerSerializer再委托给宿主的registerWidgetSerializerfunction MyWidget({ initial }: { initial: number }) { useWidgetSerializer({ serialize: () ({ value: initial }), // grid.save() 时并入 props deserialize: (data) console.log(restored, data), // updateCB/load 后回调 }); return div{initial}/div; }完整闭环grid.save()→GridStack.saveCBgsSaveAdditionalReactInfo→ 读_gridItemRef.gridComp.mergeWidgetPropsForSave(id, w)→ 合并serialize()结果进w.propsgrid.load()/updateCB→gsUpdateReactComponents→gridComp.deserializeWidget(id, w)→ 调用组件注册的deserialize。测试用例见 gridstack-react.test.tsx。六、类型使用速查与注意事项从正确的入口导入业务代码应统一从gridstack/dist/react导入GridStack、useGridStack、useWidgetSerializer等类型扩展通过该入口生效。GridStackWidget是最小序列化单元componentprops是组件模式的核心props必须是可 JSON 序列化的Recordstring, unknownel是运行时字段序列化时会被忽略gsSaveAdditionalReactInfo只拷贝component/props。懒加载优先级全局GridStackOptions.lazyLoad是兜底widget 级lazyLoad覆盖它懒加载依赖浏览器IntersectionObserveritem 移除时观察器会被自动清理。嵌套网格类型是递归的GridStackOptions.subGridOpts与GridStackWidget.subGridOpts都指向 React 版递归类型嵌套层数不限且共享父级components映射。Host API 属于内部管道除非做深度定制例如自定义 add/remove 行为否则优先使用useGridStack()/useWidgetSerializer()等公开 API它们会替你走完_gridComp链路。跨网格拖拽unregisterSyntheticItemId的微任务延迟设计保证跨网格 DnD先 remove 后 add时门户不被误卸载相关机制由pendingRemovalRef支撑。七、延伸阅读类型扩展完整源码react/projects/lib/src/types.ts主组件实现_gridComp盖章、Host API 装配、syntheticItems 渲染react/projects/lib/src/gridstack.tsxwidget 门户与GridStackWidgetContext实现react/projects/lib/src/gridstack-item.tsx静态回调addRemoveCB / saveCB / updateCB与_gridItemRef写入react/projects/lib/src/registry.ts公开钩子useGridStack/useWidgetSerializer/useGridStackItemreact/projects/lib/src/hooks.tsReact 封装层使用文档react/README.md核心类型GridStackWidget / GridStackOptions / GridStackNode / GridHTMLElement / GridItemHTMLElementdoc/API.md类型文档原始出处react/doc/api/types.md赞分享前端UI组件【免费下载链接】gridstack.jsBuild interactive dashboards in minutes.项目地址https://gitcode.com/gh_mirrors/gr/gridstack.js点击查看免费下载相关推荐Vitest 4 expect.schemaMatching 深度解析用 Zod、Valibot、ArkType 模式驱动测试断言Vitest 4 expect.schemaMatching 深度解析用 Zod、Valibot、ArkType 模式驱动测试断言 本篇指南基于 Vitest前端UI组件TypeScript与React类型系统深度解析types/react和types/react-dom核心API指南TypeScript与React类型系统深度解析types/react和types/react dom核心API指南 前言 在React与TypeScri文档教程前端OmniRoute 数据库运维指南SQLite 存储架构、迁移体系、加密备份与故障恢复全解析OmniRoute 数据库运维指南SQLite 存储架构、迁移体系、加密备份与故障恢复全解析 OmniRoute 是一个以单端点、多 Provider 路由前端UI组件上一篇终极指南5分钟用Docker一键部署ImageAI图像识别环境下一篇Dear ImGui 单文件模式3 步集成完整 GUI绕开多文件依赖创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考