From 575993fe34de86b31d1a30463ab065fd7ab52ae4 Mon Sep 17 00:00:00 2001 From: roymondchen Date: Mon, 26 Jan 2026 19:33:55 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0runtime=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/config.ts | 69 ++++ docs/runtime-api/core/app.md | 321 +++++++++++++++++ docs/runtime-api/core/devtoolApi.md | 191 ++++++++++ docs/runtime-api/core/env.md | 69 ++++ docs/runtime-api/core/eventHelper.md | 150 ++++++++ docs/runtime-api/core/flowState.md | 82 +++++ docs/runtime-api/core/iteratorContainer.md | 142 ++++++++ docs/runtime-api/core/node.md | 139 ++++++++ docs/runtime-api/core/page.md | 126 +++++++ docs/runtime-api/core/utils.md | 107 ++++++ docs/runtime-api/data-source/dataSource.md | 198 +++++++++++ .../data-source/dataSourceManager.md | 335 ++++++++++++++++++ .../runtime-api/data-source/httpDataSource.md | 221 ++++++++++++ docs/runtime-api/data-source/observedData.md | 148 ++++++++ docs/runtime-api/data-source/utils.md | 200 +++++++++++ packages/core/src/type.ts | 3 +- 16 files changed, 2499 insertions(+), 2 deletions(-) create mode 100644 docs/runtime-api/core/app.md create mode 100644 docs/runtime-api/core/devtoolApi.md create mode 100644 docs/runtime-api/core/env.md create mode 100644 docs/runtime-api/core/eventHelper.md create mode 100644 docs/runtime-api/core/flowState.md create mode 100644 docs/runtime-api/core/iteratorContainer.md create mode 100644 docs/runtime-api/core/node.md create mode 100644 docs/runtime-api/core/page.md create mode 100644 docs/runtime-api/core/utils.md create mode 100644 docs/runtime-api/data-source/dataSource.md create mode 100644 docs/runtime-api/data-source/dataSourceManager.md create mode 100644 docs/runtime-api/data-source/httpDataSource.md create mode 100644 docs/runtime-api/data-source/observedData.md create mode 100644 docs/runtime-api/data-source/utils.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 099b8dd1..3117da9a 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -30,6 +30,7 @@ export default defineConfig({ nav: [ { text: '文档', link: '/guide/', activeMatch: '/guide/' }, { text: 'API', link: '/api/editor/props', activeMatch: '/api/' }, + { text: 'Runtime API', link: '/runtime-api/core/app', activeMatch: '/runtime-api/' }, { text: '表单配置', link: '/form-config/fields/text', activeMatch: '/form-config/' }, { text: '更新日志', link: 'https://github.com/Tencent/tmagic-editor/releases' }, { text: 'Playground', link: 'https://tencent.github.io/tmagic-editor/playground/index.html' }, @@ -477,6 +478,74 @@ export default defineConfig({ } ] } + ], + '/runtime-api/': [ + { + text: '@tmagic/core', + items: [ + { + text: 'App', + link: '/runtime-api/core/app', + }, + { + text: 'Node', + link: '/runtime-api/core/node', + }, + { + text: 'Page', + link: '/runtime-api/core/page', + }, + { + text: 'EventHelper', + link: '/runtime-api/core/eventHelper', + }, + { + text: 'Env', + link: '/runtime-api/core/env', + }, + { + text: 'IteratorContainer', + link: '/runtime-api/core/iteratorContainer', + }, + { + text: 'FlowState', + link: '/runtime-api/core/flowState', + }, + { + text: 'DevtoolApi', + link: '/runtime-api/core/devtoolApi', + }, + { + text: '工具函数', + link: '/runtime-api/core/utils', + }, + ], + }, + { + text: '@tmagic/data-source', + items: [ + { + text: 'DataSourceManager', + link: '/runtime-api/data-source/dataSourceManager', + }, + { + text: 'DataSource', + link: '/runtime-api/data-source/dataSource', + }, + { + text: 'HttpDataSource', + link: '/runtime-api/data-source/httpDataSource', + }, + { + text: '观察者数据类', + link: '/runtime-api/data-source/observedData', + }, + { + text: '工具函数', + link: '/runtime-api/data-source/utils', + }, + ], + }, ] }, }, diff --git a/docs/runtime-api/core/app.md b/docs/runtime-api/core/app.md new file mode 100644 index 00000000..49cfe491 --- /dev/null +++ b/docs/runtime-api/core/app.md @@ -0,0 +1,321 @@ +# App + +`App` 是 `@tmagic/core` 的核心类,继承自 `EventEmitter`,用于管理整个应用的状态和配置。 + +## 构造函数 + +```typescript +new App(options: AppOptionsConfig) +``` + +### AppOptionsConfig + +| 参数 | 类型 | 说明 | +|------|------|------| +| `ua` | `string` | User Agent 字符串 | +| `env` | `Env` | 环境信息实例 | +| `config` | `MApp` | DSL 配置 | +| `platform` | `'editor' \| 'mobile' \| 'tv' \| 'pc'` | 平台类型 | +| `jsEngine` | `JsEngine` | JS 引擎类型 | +| `designWidth` | `number` | 设计稿宽度 | +| `curPage` | `Id` | 当前页面 ID | +| `useMock` | `boolean` | 是否使用 Mock 数据 | +| `disabledFlexible` | `boolean` | 是否禁用 flexible | +| `pageFragmentContainerType` | `string \| string[]` | 页面片段容器类型 | +| `iteratorContainerType` | `string \| string[]` | 迭代器容器类型 | +| `transformStyle` | `(style: Record) => Record` | 样式转换函数 | +| `request` | `RequestFunction` | 请求函数 | +| `dataSourceManagerInitialData` | `DataSourceManagerData` | 数据源管理器初始数据 | +| `nodeStoreInitialData` | `() => any` | 节点存储初始数据工厂函数 | +| `errorHandler` | `ErrorHandler` | 错误处理器 | +| `beforeEventHandler` | `BeforeEventHandler` | 事件处理前钩子 | +| `afterEventHandler` | `AfterEventHandler` | 事件处理后钩子 | + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `env` | `Env` | 环境信息实例 | +| `dsl` | `MApp` | DSL 配置 | +| `codeDsl` | `CodeBlockDSL` | 代码块配置 | +| `dataSourceManager` | `DataSourceManager \| undefined` | 数据源管理器 | +| `page` | `Page \| undefined` | 当前页面 | +| `pageFragments` | `Map` | 页面片段集合 | +| `platform` | `string` | 平台类型 | +| `jsEngine` | `JsEngine` | JS 引擎类型 | +| `components` | `Map` | 已注册的组件 | +| `eventHelper` | `EventHelper` | 事件助手实例 | + +## 静态方法 + +### registerNode + +- **参数:** + - `{string} type` 节点类型 + - `{typeof Node} NodeClass` 节点类 + +- **返回:** + - `{void}` + +- **详情:** + + 注册自定义节点类型,用于扩展节点功能。 + +- **示例:** + +```typescript +import App from '@tmagic/core'; + +class CustomNode extends Node { + // 自定义实现 +} + +App.registerNode('custom', CustomNode); +``` + +## 实例方法 + +### setEnv + +- **参数:** + - `{string} ua` User Agent 字符串 + +- **返回:** + - `{void}` + +- **详情:** + + 设置环境信息,会根据 UA 字符串更新 `env` 属性。 + +- **示例:** + +```typescript +import App from '@tmagic/core'; + +const app = new App({}); +app.setEnv(navigator.userAgent); +``` + +### setDesignWidth + +- **参数:** + - `{number} width` 设计稿宽度 + +- **返回:** + - `{void}` + +- **详情:** + + 设置设计稿宽度,用于响应式布局计算。 + +- **示例:** + +```typescript +app.setDesignWidth(375); +``` + +### setConfig + +- **参数:** + - `{MApp} config` DSL 配置 + - `{Id} curPage` 当前页面 ID(可选) + - `{DataSourceManagerData} initialData` 初始数据(可选) + +- **返回:** + - `void` + +- **详情:** + + 设置 DSL 配置,会初始化数据源管理器和当前页面。 + +- **示例:** + +```typescript +app.setConfig({ + id: 'app_1', + type: 'app', + items: [ + { + id: 'page_1', + type: 'page', + items: [] + } + ] +}); +``` + +### setPage + +- **参数:** + - `{Id} id` 页面 ID + +- **返回:** + - `{void}` + +- **详情:** + + 切换当前页面。 + +- **示例:** + +```typescript +app.setPage('page_2'); +``` + +### deletePage + +- **返回:** + - `{void}` + +- **详情:** + + 删除当前页面。 + +### getPage + +- **参数:** + - `{Id} id` 页面 ID(可选) + +- **返回:** + - `{Page | undefined}` + +- **详情:** + + 获取指定 ID 的页面,不传 ID 则返回当前页面。 + +- **示例:** + +```typescript +const page = app.getPage('page_1'); +``` + +### getNode + +- **参数:** + - `{Id} id` 节点 ID + - `{GetNodeOptions} options` 获取选项(可选) + +- **返回:** + - `{Node | undefined}` + +- **详情:** + + 获取指定 ID 的节点。 + +- **GetNodeOptions:** + +| 参数 | 类型 | 说明 | +|------|------|------| +| `iteratorContainerId` | `Id[]` | 迭代器容器 ID 数组 | +| `iteratorIndex` | `number[]` | 迭代器索引数组 | +| `pageFragmentContainerId` | `Id` | 页面片段容器 ID | +| `strict` | `boolean` | 是否严格模式 | + +- **示例:** + +```typescript +const node = app.getNode('button_1'); +``` + +### registerComponent + +- **参数:** + - `{string} type` 组件类型 + - `{any} Component` 组件 + +- **返回:** + - `{void}` + +- **详情:** + + 注册组件。 + +- **示例:** + +```typescript +app.registerComponent('my-button', MyButton); +``` + +### unregisterComponent + +- **参数:** + - `{string} type` 组件类型 + +- **返回:** + - `{void}` + +- **详情:** + + 取消注册组件。 + +### resolveComponent + +- **参数:** + - `{string} type` 组件类型 + +- **返回:** + - `{any}` + +- **详情:** + + 解析组件,返回已注册的组件。 + +### runCode + +- **参数:** + - `{Id} codeId` 代码块 ID + - `{object} params` 参数 + - `{any[]} args` 额外参数 + - `{FlowState} flowState` 流程状态(可选) + - `{Node} node` 节点(可选) + +- **返回:** + - `{any}` + +- **详情:** + + 执行代码块。 + +- **示例:** + +```typescript +const result = await app.runCode('code_1', { key: 'value' }); +``` + +### runDataSourceMethod + +- **参数:** + - `{Id} dsId` 数据源 ID + - `{string} methodName` 方法名 + - `{object} params` 参数 + - `{any[]} args` 额外参数 + - `{FlowState} flowState` 流程状态(可选) + - `{Node} node` 节点(可选) + +- **返回:** + - `{any}` + +- **详情:** + + 执行数据源方法。 + +- **示例:** + +```typescript +const result = await app.runDataSourceMethod('ds_1', 'fetchData', { id: 123 }); +``` + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁应用实例,清理所有资源。 + +- **示例:** + +```typescript +app.destroy(); +``` diff --git a/docs/runtime-api/core/devtoolApi.md b/docs/runtime-api/core/devtoolApi.md new file mode 100644 index 00000000..4703908f --- /dev/null +++ b/docs/runtime-api/core/devtoolApi.md @@ -0,0 +1,191 @@ +# DevtoolApi + +`DevtoolApi` 是 `@tmagic/core` 提供给开发工具使用的 API 接口类。 + +## 构造函数 + +```typescript +new DevtoolApi(options: DevtoolApiOptions) +``` + +### DevtoolApiOptions + +| 参数 | 类型 | 说明 | +|------|------|------| +| `app` | `App` | 应用实例 | + +## 实例方法 + +### openPop + +- **参数:** + - `{Id} popId` 弹窗组件 ID + +- **返回:** + - `{void}` + +- **详情:** + + 打开指定的弹窗组件。 + +- **示例:** + +```typescript +devtoolApi.openPop('dialog_1'); +``` + +### setDataSourceData + +- **参数:** + - `{Id} dsId` 数据源 ID + - `{any} data` 数据 + - `{string} path` 数据路径(可选) + +- **返回:** + - `{void}` + +- **详情:** + + 设置数据源的数据。 + +- **示例:** + +```typescript +// 设置整个数据源数据 +devtoolApi.setDataSourceData('ds_1', { name: 'test' }); + +// 设置数据源的某个字段 +devtoolApi.setDataSourceData('ds_1', 'newValue', 'user.name'); +``` + +### requestDataSource + +- **参数:** + - `{Id} dsId` 数据源 ID + +- **返回:** + - `{Promise}` + +- **详情:** + + 触发 HTTP 数据源的请求。 + +- **示例:** + +```typescript +await devtoolApi.requestDataSource('http_ds_1'); +``` + +### getDisplayCondRealValue + +- **参数:** + - `{Id} nodeId` 节点 ID + - `{CondItem} condItem` 条件项 + +- **返回:** + - `{any}` + +- **详情:** + + 获取显示条件的实际计算值。 + +### callHook + +- **参数:** + - `{Id} nodeId` 节点 ID + - `{string} hookName` 钩子名称 + - `{any} hookData` 钩子数据 + +- **返回:** + - `{Promise}` + +- **详情:** + + 调用节点的钩子函数。 + +- **示例:** + +```typescript +await devtoolApi.callHook('button_1', 'mounted', { data: 'test' }); +``` + +### trigger + +- **参数:** + - `{Id} nodeId` 节点 ID + - `{EventConfig[]} events` 事件配置数组 + +- **返回:** + - `{Promise}` + +- **详情:** + + 触发节点的事件。 + +- **示例:** + +```typescript +await devtoolApi.trigger('button_1', [ + { + name: 'click', + actions: [{ actionType: 'code', codeId: 'code_1' }] + } +]); +``` + +### isValueIncludeDataSource + +- **参数:** + - `{any} value` 要检查的值 + +- **返回:** + - `{boolean}` + +- **详情:** + + 检查值是否包含数据源引用。 + +- **示例:** + +```typescript +const hasDs = devtoolApi.isValueIncludeDataSource('${ds_1.field}'); +console.log(hasDs); // true +``` + +### compileDataSourceValue + +- **参数:** + - `{any} value` 包含数据源引用的值 + +- **返回:** + - `{any}` + +- **详情:** + + 编译数据源值,将数据源引用替换为实际值。 + +- **示例:** + +```typescript +const compiled = devtoolApi.compileDataSourceValue('用户名:${ds_1.user.name}'); +``` + +### updateCode + +- **参数:** + - `{Id} codeId` 代码块 ID + - `{any} value` 新值 + - `{string} path` 路径(可选) + +- **返回:** + - `{void}` + +- **详情:** + + 更新代码块的内容。 + +- **示例:** + +```typescript +devtoolApi.updateCode('code_1', 'return data.value * 2;', 'content'); +``` diff --git a/docs/runtime-api/core/env.md b/docs/runtime-api/core/env.md new file mode 100644 index 00000000..3a4738a8 --- /dev/null +++ b/docs/runtime-api/core/env.md @@ -0,0 +1,69 @@ +# Env + +`Env` 是 `@tmagic/core` 的环境检测类,用于检测当前运行环境的设备和系统信息。 + +## 构造函数 + +```typescript +new Env(ua?: string) +``` + +### 参数 + +| 参数 | 类型 | 说明 | +|------|------|------| +| `ua` | `string` | User Agent 字符串(可选,默认使用 `navigator.userAgent`) | + +## 属性 + +所有属性均为只读布尔值: + +| 属性 | 类型 | 说明 | +|------|------|------| +| `isIos` | `boolean` | 是否为 iOS 系统 | +| `isIphone` | `boolean` | 是否为 iPhone 设备 | +| `isIpad` | `boolean` | 是否为 iPad 设备 | +| `isAndroid` | `boolean` | 是否为 Android 系统 | +| `isAndroidPad` | `boolean` | 是否为 Android 平板 | +| `isMac` | `boolean` | 是否为 Mac 系统 | +| `isWin` | `boolean` | 是否为 Windows 系统 | +| `isMqq` | `boolean` | 是否在手机 QQ 中 | +| `isWechat` | `boolean` | 是否在微信中 | +| `isWeb` | `boolean` | 是否为 Web 环境 | +| `isOpenHarmony` | `boolean` | 是否为鸿蒙系统 | + +## 使用示例 + +```typescript +import { Env } from '@tmagic/core'; + +// 使用当前浏览器的 UA +const env = new Env(); + +if (env.isIos) { + console.log('当前是 iOS 设备'); +} + +if (env.isWechat) { + console.log('在微信中打开'); +} + +// 使用自定义 UA +const customEnv = new Env('Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X)'); +console.log(customEnv.isIphone); // true +``` + +## 在 App 中使用 + +```typescript +import App from '@tmagic/core'; + +const app = new App({ + ua: navigator.userAgent +}); + +// 通过 app.env 访问环境信息 +if (app.env.isAndroid) { + // Android 特定逻辑 +} +``` diff --git a/docs/runtime-api/core/eventHelper.md b/docs/runtime-api/core/eventHelper.md new file mode 100644 index 00000000..c55cf2bb --- /dev/null +++ b/docs/runtime-api/core/eventHelper.md @@ -0,0 +1,150 @@ +# EventHelper + +`EventHelper` 是 `@tmagic/core` 的事件助手类,继承自 `EventEmitter`,用于管理组件间的事件联动。 + +## 构造函数 + +```typescript +new EventHelper(options: EventHelperOptions) +``` + +### EventHelperOptions + +| 参数 | 类型 | 说明 | +|------|------|------| +| `app` | `App` | 应用实例 | + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `app` | `App` | 应用实例 | + +## 实例方法 + +### initEvents + +- **返回:** + - `{void}` + +- **详情:** + + 初始化所有节点的事件。通常在页面加载时调用。 + +- **示例:** + +```typescript +eventHelper.initEvents(); +``` + +### bindNodeEvents + +- **参数:** + - `{Node} node` 节点实例 + +- **返回:** + - `{void}` + +- **详情:** + + 为单个节点绑定事件处理。 + +- **示例:** + +```typescript +eventHelper.bindNodeEvents(node); +``` + +### removeNodeEvents + +- **返回:** + - `{void}` + +- **详情:** + + 移除所有节点的事件绑定。 + +### bindDataSourceEvents + +- **返回:** + - `{void}` + +- **详情:** + + 绑定数据源事件,监听数据源变化并触发相应的组件更新。 + +### removeDataSourceEvents + +- **参数:** + - `{DataSourceSchema[]} dataSourceList` 数据源列表(可选) + +- **返回:** + - `{void}` + +- **详情:** + + 移除数据源事件绑定。 + +### getEventQueue + +- **返回:** + - `{EventConfig[]}` + +- **详情:** + + 获取当前事件队列。 + +### addEventToQueue + +- **参数:** + - `{EventConfig} event` 事件配置 + +- **返回:** + - `{void}` + +- **详情:** + + 将事件添加到队列中等待处理。 + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁事件助手,清理所有事件绑定。 + +## 支持的动作类型 + +EventHelper 支持以下动作类型(ActionType): + +| 类型 | 说明 | +|------|------| +| `ActionType.COMP` | 组件动作,调用目标组件的方法 | +| `ActionType.CODE` | 代码块执行 | +| `ActionType.DATA_SOURCE` | 数据源方法调用 | + +### 事件配置示例 + +```typescript +const eventConfig = { + name: 'click', + actions: [ + { + actionType: 'comp', + to: 'button_2', + method: 'show' + }, + { + actionType: 'code', + codeId: 'code_1' + }, + { + actionType: 'dataSource', + dataSourceId: 'ds_1', + methodName: 'fetchData' + } + ] +}; +``` diff --git a/docs/runtime-api/core/flowState.md b/docs/runtime-api/core/flowState.md new file mode 100644 index 00000000..1be37594 --- /dev/null +++ b/docs/runtime-api/core/flowState.md @@ -0,0 +1,82 @@ +# FlowState + +`FlowState` 是 `@tmagic/core` 的流程状态类,用于控制事件动作流程的执行。 + +## 构造函数 + +```typescript +new FlowState() +``` + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `isAbort` | `boolean` | 当前流程是否已中止 | + +## 实例方法 + +### abort + +- **返回:** + - `{void}` + +- **详情:** + + 中止当前流程。调用后 `isAbort` 变为 `true`,后续的事件动作将不再执行。 + +- **示例:** + +```typescript +import { FlowState } from '@tmagic/core'; + +const flowState = new FlowState(); + +// 在某个条件下中止流程 +if (shouldStop) { + flowState.abort(); +} + +// 检查是否已中止 +if (flowState.isAbort) { + console.log('流程已中止'); +} +``` + +### reset + +- **返回:** + - `{void}` + +- **详情:** + + 重置流程状态,将 `isAbort` 恢复为 `false`。 + +- **示例:** + +```typescript +flowState.reset(); +console.log(flowState.isAbort); // false +``` + +## 使用场景 + +FlowState 常用于控制事件动作链的执行流程: + +```typescript +import App, { FlowState } from '@tmagic/core'; + +const app = new App({ /* options */ }); + +// 创建流程状态 +const flowState = new FlowState(); + +// 执行代码块时传入流程状态 +await app.runCode('validateCode', {}, [], flowState); + +// 如果验证失败,代码块内部可以调用 flowState.abort() +// 后续的动作将不会执行 +if (!flowState.isAbort) { + await app.runCode('submitCode', {}, [], flowState); +} +``` diff --git a/docs/runtime-api/core/iteratorContainer.md b/docs/runtime-api/core/iteratorContainer.md new file mode 100644 index 00000000..001a61e9 --- /dev/null +++ b/docs/runtime-api/core/iteratorContainer.md @@ -0,0 +1,142 @@ +# IteratorContainer + +`IteratorContainer` 是 `@tmagic/core` 的迭代容器类,继承自 `Node`,用于循环渲染的容器组件。 + +## 构造函数 + +```typescript +new IteratorContainer(options: NodeOptions) +``` + +参数与 [Node](./node.md) 构造函数相同。 + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `nodes` | `Map[]` | 每个迭代项的节点映射数组 | + +继承自 Node 的属性请参见 [Node 属性](./node.md#属性)。 + +## 实例方法 + +### setData + +- **参数:** + - `{MNode} data` 节点数据 + +- **返回:** + - `{void}` + +- **详情:** + + 设置数据,会重置所有迭代项的节点。 + +- **示例:** + +```typescript +iteratorContainer.setData({ + id: 'iterator_1', + type: 'iterator-container', + iteratorData: [{ name: 'item1' }, { name: 'item2' }], + items: [/* 子节点配置 */] +}); +``` + +### resetNodes + +- **返回:** + - `{void}` + +- **详情:** + + 重置所有迭代项的节点,会清空并重新初始化。 + +### initNode + +- **参数:** + - `{MNode} config` 节点配置 + - `{Node} parent` 父节点 + - `{Map} map` 节点映射表 + +- **返回:** + - `{Node}` + +- **详情:** + + 在指定的节点映射表中初始化节点。 + +### setNodes + +- **参数:** + - `{Map} nodes` 节点映射表 + - `{number} index` 迭代索引 + +- **返回:** + - `{void}` + +- **详情:** + + 设置指定索引的节点映射表。 + +- **示例:** + +```typescript +iteratorContainer.setNodes(nodesMap, 0); +``` + +### getNode + +- **参数:** + - `{Id} id` 节点 ID + - `{number} index` 迭代索引(可选,默认为 0) + +- **返回:** + - `{Node | undefined}` + +- **详情:** + + 获取指定迭代索引中的节点。 + +- **示例:** + +```typescript +// 获取第一个迭代项中的节点 +const node = iteratorContainer.getNode('button_1', 0); + +// 获取第二个迭代项中的节点 +const node2 = iteratorContainer.getNode('button_1', 1); +``` + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁迭代容器及其所有迭代项的节点。 + +## 使用场景 + +IteratorContainer 常用于列表渲染场景,例如: + +```typescript +// DSL 配置示例 +const iteratorConfig = { + id: 'iterator_1', + type: 'iterator-container', + iteratorData: [ + { id: 1, title: '项目1' }, + { id: 2, title: '项目2' }, + { id: 3, title: '项目3' } + ], + items: [ + { + id: 'text_tpl', + type: 'text', + text: '${item.title}' + } + ] +}; +``` diff --git a/docs/runtime-api/core/node.md b/docs/runtime-api/core/node.md new file mode 100644 index 00000000..5cfad3fc --- /dev/null +++ b/docs/runtime-api/core/node.md @@ -0,0 +1,139 @@ +# Node + +`Node` 是 `@tmagic/core` 的节点基类,继承自 `EventEmitter`,表示 DSL 中的一个节点。 + +## 构造函数 + +```typescript +new Node(options: NodeOptions) +``` + +### NodeOptions + +| 参数 | 类型 | 说明 | +|------|------|------| +| `config` | `MNode` | 节点配置 | +| `parent` | `Node` | 父节点(可选) | +| `page` | `Page` | 所属页面 | +| `app` | `App` | 应用实例 | + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `data` | `MNode` | 节点配置数据 | +| `style` | `object` | 节点样式 | +| `events` | `EventConfig[]` | 事件配置 | +| `instance` | `any` | 组件实例 | +| `page` | `Page` | 所属页面 | +| `parent` | `Node \| undefined` | 父节点 | +| `app` | `App` | 应用实例 | +| `store` | `Store` | 节点存储 | +| `eventKeys` | `Map` | 事件键映射 | + +## 实例方法 + +### setData + +- **参数:** + - `{MNode} data` 节点数据 + +- **返回:** + - `{void}` + +- **详情:** + + 设置节点数据,会更新 `data`、`style` 和 `events` 属性。 + +- **示例:** + +```typescript +node.setData({ + id: 'button_1', + type: 'button', + style: { width: 100 }, + events: [] +}); +``` + +### addEventToQueue + +- **参数:** + - `{EventConfig} event` 事件配置 + +- **返回:** + - `{void}` + +- **详情:** + + 将事件添加到事件队列,等待绑定到组件实例。 + +### setInstance + +- **参数:** + - `{any} instance` 组件实例 + +- **返回:** + - `{void}` + +- **详情:** + + 设置组件实例,并绑定队列中的事件。 + +- **示例:** + +```typescript +// 通常在组件挂载时调用 +node.setInstance(componentInstance); +``` + +### runHookCode + +- **参数:** + - `{'created' | 'mounted'} hook` 钩子名称 + - `{object} params` 参数 + +- **返回:** + - `{Promise}` + +- **详情:** + + 执行节点的钩子代码。 + +- **示例:** + +```typescript +await node.runHookCode('mounted', { data: someData }); +``` + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁节点,清理事件监听和组件实例。 + +## 生命周期事件 + +Node 实例会触发以下生命周期事件: + +| 事件名 | 说明 | +|--------|------| +| `created` | 组件创建完成时触发 | +| `mounted` | 组件挂载完成时触发 | +| `destroy` | 组件销毁时触发 | +| `update-data` | 数据更新时触发 | + +### 监听示例 + +```typescript +node.on('mounted', () => { + console.log('组件已挂载'); +}); + +node.on('update-data', (newData) => { + console.log('数据已更新', newData); +}); +``` diff --git a/docs/runtime-api/core/page.md b/docs/runtime-api/core/page.md new file mode 100644 index 00000000..74eec4af --- /dev/null +++ b/docs/runtime-api/core/page.md @@ -0,0 +1,126 @@ +# Page + +`Page` 是 `@tmagic/core` 的页面类,继承自 `Node`,用于管理页面及其子节点。 + +## 构造函数 + +```typescript +new Page(options: PageOptions) +``` + +### PageOptions + +继承自 NodeOptions,参见 [Node](./node.md) 构造函数。 + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `nodes` | `Map` | 页面内所有节点的映射表 | + +继承自 Node 的属性请参见 [Node 属性](./node.md#属性)。 + +## 实例方法 + +### initNode + +- **参数:** + - `{MNode} config` 节点配置 + - `{Node} parent` 父节点(可选) + +- **返回:** + - `{Node}` + +- **详情:** + + 初始化节点,根据配置创建节点实例并添加到页面。会递归初始化子节点。 + +- **示例:** + +```typescript +const node = page.initNode({ + id: 'button_1', + type: 'button', + style: { width: 100 } +}); +``` + +### getNode + +- **参数:** + - `{Id} id` 节点 ID + - `{GetNodeOptions} options` 获取选项(可选) + +- **返回:** + - `{Node | undefined}` + +- **详情:** + + 获取页面中指定 ID 的节点。支持从迭代器容器和页面片段中获取节点。 + +- **GetNodeOptions:** + +| 参数 | 类型 | 说明 | +|------|------|------| +| `iteratorContainerId` | `Id[]` | 迭代器容器 ID 数组 | +| `iteratorIndex` | `number[]` | 迭代器索引数组 | +| `pageFragmentContainerId` | `Id` | 页面片段容器 ID | +| `strict` | `boolean` | 是否严格模式 | + +- **示例:** + +```typescript +const node = page.getNode('button_1'); + +// 从迭代器中获取 +const iteratorNode = page.getNode('item_1', { + iteratorContainerId: ['iterator_1'], + iteratorIndex: [0] +}); +``` + +### setNode + +- **参数:** + - `{Id} id` 节点 ID + - `{Node} node` 节点实例 + +- **返回:** + - `{void}` + +- **详情:** + + 设置页面中的节点。 + +### deleteNode + +- **参数:** + - `{Id} id` 节点 ID + +- **返回:** + - `{void}` + +- **详情:** + + 删除页面中指定 ID 的节点。 + +- **示例:** + +```typescript +page.deleteNode('button_1'); +``` + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁页面及其所有子节点。 + +- **示例:** + +```typescript +page.destroy(); +``` diff --git a/docs/runtime-api/core/utils.md b/docs/runtime-api/core/utils.md new file mode 100644 index 00000000..a7a29b74 --- /dev/null +++ b/docs/runtime-api/core/utils.md @@ -0,0 +1,107 @@ +# 工具函数 + +`@tmagic/core` 导出的工具函数。 + +## style2Obj + +- **参数:** + - `{string} style` CSS 样式字符串 + +- **返回:** + - `{object}` 样式对象 + +- **详情:** + + 将 CSS 样式字符串转换为对象格式。 + +- **示例:** + +```typescript +import { style2Obj } from '@tmagic/core'; + +const styleObj = style2Obj('width: 100px; height: 200px;'); +console.log(styleObj); // { width: '100px', height: '200px' } +``` + +## fillBackgroundImage + +- **参数:** + - `{string} value` 背景图片 URL + +- **返回:** + - `{string}` 完整的 CSS 背景图片值 + +- **详情:** + + 填充背景图片 URL 为完整的 CSS 格式。 + +- **示例:** + +```typescript +import { fillBackgroundImage } from '@tmagic/core'; + +const bg = fillBackgroundImage('https://example.com/image.png'); +console.log(bg); // 'url(https://example.com/image.png)' +``` + +## getTransform + +- **参数:** + - `{object} value` transform 配置 + - `{JsEngine} jsEngine` JS 引擎类型 + +- **返回:** + - `{string}` CSS transform 字符串 + +- **详情:** + + 根据配置生成 CSS transform 字符串,会根据 JS 引擎类型进行适配。 + +## transformStyle + +- **参数:** + - `{object} style` 样式对象 + - `{JsEngine} jsEngine` JS 引擎类型 + +- **返回:** + - `{object}` 转换后的样式对象 + +- **详情:** + + 转换样式对象,将数值转换为 rem 单位(移动端适配)。 + +- **示例:** + +```typescript +import { transformStyle } from '@tmagic/core'; + +const style = transformStyle({ width: 100, height: 200 }, 'browser'); +console.log(style); // { width: '1rem', height: '2rem' } +``` + +## 常量 + +### COMMON_EVENT_PREFIX + +- **值:** `'magic:common:events:'` + +- **详情:** + + 通用事件前缀。 + +### COMMON_METHOD_PREFIX + +- **值:** `'magic:common:actions:'` + +- **详情:** + + 通用方法前缀。 + +- **示例:** + +```typescript +import { COMMON_EVENT_PREFIX, COMMON_METHOD_PREFIX } from '@tmagic/core'; + +const eventKey = `${COMMON_EVENT_PREFIX}click`; +const methodKey = `${COMMON_METHOD_PREFIX}show`; +``` diff --git a/docs/runtime-api/data-source/dataSource.md b/docs/runtime-api/data-source/dataSource.md new file mode 100644 index 00000000..d08d192c --- /dev/null +++ b/docs/runtime-api/data-source/dataSource.md @@ -0,0 +1,198 @@ +# DataSource(基础数据源) + +`DataSource` 是 `@tmagic/data-source` 的基础数据源类,用于静态数据管理。 + +## 构造函数 + +```typescript +new DataSource(options: DataSourceOptions) +``` + +### DataSourceOptions + +| 参数 | 类型 | 说明 | +|------|------|------| +| `schema` | `DataSourceSchema` | 数据源配置 | +| `app` | `TMagicApp` | 应用实例 | +| `initialData` | `Record` | 初始数据(可选) | +| `useMock` | `boolean` | 使用 Mock 数据(可选) | +| `request` | `RequestFunction` | 请求函数(可选) | +| `ObservedDataClass` | `ObservedDataClass` | 观察者数据类(可选) | + +### DataSourceSchema + +| 参数 | 类型 | 说明 | +|------|------|------| +| `id` | `string` | 数据源 ID | +| `type` | `'base'` | 数据源类型 | +| `title` | `string` | 数据源标题(可选) | +| `description` | `string` | 数据源描述(可选) | +| `fields` | `DataSchema[]` | 字段配置 | +| `methods` | `CodeBlockContent[]` | 自定义方法配置(可选) | +| `mocks` | `MockSchema` | Mock 数据配置(可选) | +| `events` | `EventConfig[]` | 事件配置(可选) | + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `id` | `string` | 数据源 ID(只读) | +| `type` | `string` | 数据源类型,值为 `'base'` | +| `schema` | `DataSourceSchema` | 配置 schema | +| `fields` | `DataSchema[]` | 字段配置 | +| `methods` | `CodeBlockContent[]` | 自定义方法配置 | +| `data` | `any` | 当前数据 | +| `isInit` | `boolean` | 是否已初始化 | + +## 实例方法 + +### setData + +- **参数:** + - `{any} data` 数据 + - `{string} path` 数据路径(可选) + +- **返回:** + - `{void}` + +- **详情:** + + 设置数据源数据。如果指定路径,则只更新该路径的数据。 + +- **示例:** + +```typescript +// 设置整个数据 +ds.setData({ name: 'test', count: 10 }); + +// 设置特定路径的数据 +ds.setData('newValue', 'user.name'); +``` + +### setValue + +- **参数:** + - `{string} path` 数据路径 + - `{any} data` 数据 + +- **返回:** + - `{void}` + +- **详情:** + + 按路径设置数据,等同于 `setData(data, path)`。 + +- **示例:** + +```typescript +ds.setValue('user.age', 25); +``` + +### onDataChange + +- **参数:** + - `{string} path` 数据路径 + - `{Function} callback` 回调函数 + +- **返回:** + - `{void}` + +- **详情:** + + 监听指定路径的数据变化。 + +- **示例:** + +```typescript +ds.onDataChange('user.name', (newVal) => { + console.log('用户名变更:', newVal); +}); +``` + +### offDataChange + +- **参数:** + - `{string} path` 数据路径 + - `{Function} callback` 回调函数 + +- **返回:** + - `{void}` + +- **详情:** + + 取消监听数据变化。 + +### getDefaultData + +- **返回:** + - `{any}` 默认数据 + +- **详情:** + + 根据字段配置获取默认数据。 + +### init + +- **返回:** + - `{Promise}` + +- **详情:** + + 初始化数据源。 + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁数据源,清理资源。 + +## 事件 + +DataSource 继承自 EventEmitter,支持以下事件: + +| 事件名 | 说明 | +|--------|------| +| `change` | 数据变化时触发 | + +### 示例 + +```typescript +ds.on('change', () => { + console.log('数据已变化', ds.data); +}); +``` + +## 字段配置 (DataSchema) + +| 参数 | 类型 | 说明 | +|------|------|------| +| `name` | `string` | 字段名 | +| `type` | `string` | 字段类型 | +| `title` | `string` | 字段标题(可选) | +| `description` | `string` | 字段描述(可选) | +| `defaultValue` | `any` | 默认值(可选) | +| `fields` | `DataSchema[]` | 子字段(对象类型时)(可选) | + +### 字段配置示例 + +```typescript +const schema = { + id: 'user_ds', + type: 'base', + fields: [ + { name: 'id', type: 'number', defaultValue: 0 }, + { name: 'name', type: 'string', defaultValue: '' }, + { + name: 'profile', + type: 'object', + fields: [ + { name: 'avatar', type: 'string' }, + { name: 'bio', type: 'string' } + ] + } + ] +}; +``` diff --git a/docs/runtime-api/data-source/dataSourceManager.md b/docs/runtime-api/data-source/dataSourceManager.md new file mode 100644 index 00000000..fa80d98a --- /dev/null +++ b/docs/runtime-api/data-source/dataSourceManager.md @@ -0,0 +1,335 @@ +# DataSourceManager + +`DataSourceManager` 是 `@tmagic/data-source` 的核心类,用于管理所有数据源的生命周期、数据编译和事件分发。 + +## 构造函数 + +```typescript +new DataSourceManager(options: DataSourceManagerOptions) +``` + +### DataSourceManagerOptions + +| 参数 | 类型 | 说明 | +|------|------|------| +| `app` | `TMagicApp` | 应用实例 | +| `initialData` | `DataSourceManagerData` | 初始数据(可选,用于 SSR) | +| `useMock` | `boolean` | 是否使用 Mock 数据(可选) | + +## 属性 + +| 属性 | 类型 | 说明 | +|------|------|------| +| `app` | `TMagicApp` | 应用实例 | +| `dataSourceMap` | `Map` | 数据源映射表 | +| `data` | `DataSourceManagerData` | 所有数据源的数据 | +| `initialData` | `DataSourceManagerData` | 初始化数据 | +| `useMock` | `boolean` | 是否使用 Mock 数据 | + +## 静态方法 + +### register + +- **参数:** + - `{string} type` 数据源类型 + - `{typeof DataSource} dataSourceClass` 数据源类 + +- **返回:** + - `{void}` + +- **详情:** + + 注册自定义数据源类型。 + +- **示例:** + +```typescript +import { DataSourceManager } from '@tmagic/data-source'; + +class CustomDataSource extends DataSource { + // 自定义实现 +} + +DataSourceManager.register('custom', CustomDataSource); +``` + +### getDataSourceClass + +- **参数:** + - `{string} type` 数据源类型 + +- **返回:** + - `{typeof DataSource | undefined}` + +- **详情:** + + 获取已注册的数据源类。 + +### clearDataSourceClass + +- **返回:** + - `{void}` + +- **详情:** + + 清除所有已注册的数据源类(保留 `base` 和 `http`)。 + +### registerObservedData + +- **参数:** + - `{ObservedDataClass} observedDataClass` 观察者数据类 + +- **返回:** + - `{void}` + +- **详情:** + + 注册自定义的观察者数据类。 + +## 实例方法 + +### init + +- **参数:** + - `{DataSourceSchema[]} ds` 数据源配置数组 + +- **返回:** + - `{Promise}` + +- **详情:** + + 初始化数据源,会创建所有配置的数据源实例并初始化。 + +- **示例:** + +```typescript +await dataSourceManager.init([ + { + id: 'ds_1', + type: 'base', + fields: [{ name: 'count', defaultValue: 0 }] + }, + { + id: 'http_1', + type: 'http', + options: { url: '/api/data' } + } +]); +``` + +### get + +- **参数:** + - `{string} id` 数据源 ID + +- **返回:** + - `{DataSource | undefined}` + +- **详情:** + + 获取指定 ID 的数据源实例。 + +- **示例:** + +```typescript +const ds = dataSourceManager.get('ds_1'); +``` + +### addDataSource + +- **参数:** + - `{DataSourceSchema} config` 数据源配置 + +- **返回:** + - `{DataSource}` + +- **详情:** + + 添加新的数据源。 + +- **示例:** + +```typescript +const ds = dataSourceManager.addDataSource({ + id: 'new_ds', + type: 'base', + fields: [] +}); +``` + +### removeDataSource + +- **参数:** + - `{string} id` 数据源 ID + +- **返回:** + - `{void}` + +- **详情:** + + 移除指定的数据源。 + +### setData + +- **参数:** + - `{DataSourceSchema} ds` 数据源配置 + - `{ChangeEvent} changeEvent` 变化事件(可选) + +- **返回:** + - `{void}` + +- **详情:** + + 设置数据源数据。 + +### updateSchema + +- **参数:** + - `{DataSourceSchema[]} schemas` 数据源配置数组 + +- **返回:** + - `{Promise}` + +- **详情:** + + 更新数据源 DSL 配置,会自动处理新增、更新和删除。 + +### compiledNode + +- **参数:** + - `{MNode} node` 节点配置 + - `{string} sourceId` 数据源 ID(可选) + - `{boolean} deep` 是否深度编译(可选) + +- **返回:** + - `{MNode}` + +- **详情:** + + 编译节点 DSL 中的数据源配置,将数据源引用替换为实际值。 + +- **示例:** + +```typescript +const compiledNode = dataSourceManager.compiledNode({ + id: 'text_1', + type: 'text', + text: '${ds_1.username}' +}); +// compiledNode.text 会被替换为实际的用户名 +``` + +### compliedConds + +- **参数:** + - `{MNode} node` 节点配置 + - `{object} data` 数据上下文(可选) + +- **返回:** + - `{boolean}` + +- **详情:** + + 编译显示条件,返回节点是否应该显示。 + +- **示例:** + +```typescript +const shouldShow = dataSourceManager.compliedConds(node); +``` + +### compliedIteratorItemConds + +- **参数:** + - `{object} itemData` 迭代项数据 + - `{MNode} node` 节点配置 + - `{string} field` 条件字段名 + +- **返回:** + - `{boolean}` + +- **详情:** + + 编译迭代器项的显示条件。 + +### compliedIteratorItems + +- **参数:** + - `{object} itemData` 迭代项数据 + - `{MNode[]} nodes` 节点配置数组 + - `{string} field` 字段名 + +- **返回:** + - `{MNode[]}` + +- **详情:** + + 编译迭代器项的节点配置。 + +### onDataChange + +- **参数:** + - `{string} id` 数据源 ID + - `{string} path` 数据路径 + - `{Function} callback` 回调函数 + +- **返回:** + - `{void}` + +- **详情:** + + 监听数据源数据变化。 + +- **示例:** + +```typescript +dataSourceManager.onDataChange('ds_1', 'user.name', (newVal) => { + console.log('用户名变更:', newVal); +}); +``` + +### offDataChange + +- **参数:** + - `{string} id` 数据源 ID + - `{string} path` 数据路径 + - `{Function} callback` 回调函数 + +- **返回:** + - `{void}` + +- **详情:** + + 取消监听数据源数据变化。 + +### destroy + +- **返回:** + - `{void}` + +- **详情:** + + 销毁数据源管理器,清理所有数据源。 + +## 事件 + +DataSourceManager 继承自 EventEmitter,支持以下事件: + +| 事件名 | 说明 | 回调参数 | +|--------|------|----------| +| `change` | 数据源数据变化 | `(dsId, path, newVal)` | +| `init` | 所有数据源初始化完成 | 无 | +| `registered-all` | 所有数据源注册完成 | 无 | +| `update-data` | 更新节点数据 | `(node, sourceId)` | + +### 事件监听示例 + +```typescript +dataSourceManager.on('change', (dsId, path, newVal) => { + console.log(`数据源 ${dsId} 的 ${path} 变更为:`, newVal); +}); + +dataSourceManager.on('init', () => { + console.log('所有数据源初始化完成'); +}); +``` diff --git a/docs/runtime-api/data-source/httpDataSource.md b/docs/runtime-api/data-source/httpDataSource.md new file mode 100644 index 00000000..e2a5e34f --- /dev/null +++ b/docs/runtime-api/data-source/httpDataSource.md @@ -0,0 +1,221 @@ +# HttpDataSource(HTTP 数据源) + +`HttpDataSource` 是 `@tmagic/data-source` 的 HTTP 数据源类,继承自 `DataSource`,用于通过 HTTP 请求获取数据。 + +## 构造函数 + +```typescript +new HttpDataSource(options: DataSourceOptions) +``` + +参数参见 [DataSource](./dataSource.md) 构造函数。 + +### HttpDataSourceSchema + +继承自 DataSourceSchema,额外包含: + +| 参数 | 类型 | 说明 | +|------|------|------| +| `type` | `'http'` | 数据源类型 | +| `options` | `HttpOptionsSchema` | HTTP 请求配置 | +| `responseOptions` | `{ dataPath?: string }` | 响应数据配置(可选) | +| `autoFetch` | `boolean` | 是否自动请求(可选) | +| `beforeRequest` | `Function \| string` | 请求前钩子(可选) | +| `afterResponse` | `Function \| string` | 响应后钩子(可选) | + +### HttpOptionsSchema + +| 参数 | 类型 | 说明 | +|------|------|------| +| `url` | `string \| Function` | 请求链接 | +| `method` | `'GET' \| 'POST'` | 请求方法(可选,默认 GET) | +| `params` | `object \| Function` | Query 参数(可选) | +| `data` | `object \| Function` | Body 数据(可选) | +| `headers` | `object \| Function` | 请求头(可选) | + +## 属性 + +继承自 DataSource 的属性,额外包含: + +| 属性 | 类型 | 说明 | +|------|------|------| +| `isLoading` | `boolean` | 是否正在请求 | +| `error` | `{ msg?: string, code?: string }` | 错误信息 | +| `httpOptions` | `HttpOptionsSchema` | 请求配置 | + +## 实例方法 + +### request + +- **参数:** + - `{HttpOptionsSchema} options` 请求选项(可选) + +- **返回:** + - `{Promise}` 响应数据 + +- **详情:** + + 发起 HTTP 请求。可以传入选项覆盖默认配置。 + +- **示例:** + +```typescript +// 使用默认配置请求 +const data = await httpDs.request(); + +// 覆盖部分配置 +const data = await httpDs.request({ + params: { page: 1, size: 10 } +}); +``` + +### get + +- **参数:** + - `{HttpOptionsSchema} options` 请求选项 + +- **返回:** + - `{Promise}` 响应数据 + +- **详情:** + + 发起 GET 请求。 + +- **示例:** + +```typescript +const data = await httpDs.get({ + url: '/api/users', + params: { id: 1 } +}); +``` + +### post + +- **参数:** + - `{HttpOptionsSchema} options` 请求选项 + +- **返回:** + - `{Promise}` 响应数据 + +- **详情:** + + 发起 POST 请求。 + +- **示例:** + +```typescript +const data = await httpDs.post({ + url: '/api/users', + data: { name: 'test' } +}); +``` + +## 配置示例 + +### 基础配置 + +```typescript +const httpDsSchema = { + id: 'user_api', + type: 'http', + title: '用户接口', + options: { + url: '/api/user', + method: 'GET', + params: { id: 1 } + }, + autoFetch: true, + fields: [ + { name: 'id', type: 'number' }, + { name: 'name', type: 'string' } + ] +}; +``` + +### 动态参数配置 + +```typescript +const httpDsSchema = { + id: 'dynamic_api', + type: 'http', + options: { + url: (app) => `/api/users/${app.page.data.userId}`, + params: (app) => ({ token: app.getToken() }) + } +}; +``` + +### 请求钩子配置 + +```typescript +const httpDsSchema = { + id: 'hooked_api', + type: 'http', + options: { + url: '/api/data', + method: 'POST' + }, + // 请求前处理 + beforeRequest: (options, app) => { + options.headers = { + ...options.headers, + Authorization: `Bearer ${app.token}` + }; + return options; + }, + // 响应后处理 + afterResponse: (response, app) => { + if (response.code !== 0) { + throw new Error(response.message); + } + return response.data; + }, + // 响应数据路径 + responseOptions: { + dataPath: 'data.list' + } +}; +``` + +### 使用代码块作为钩子 + +```typescript +const httpDsSchema = { + id: 'code_hook_api', + type: 'http', + options: { + url: '/api/data' + }, + // 引用代码块 ID + beforeRequest: 'code_before_request', + afterResponse: 'code_after_response' +}; +``` + +## 自动请求 + +当 `autoFetch` 设置为 `true` 时,数据源在初始化时会自动发起请求: + +```typescript +const httpDsSchema = { + id: 'auto_api', + type: 'http', + options: { + url: '/api/init-data' + }, + autoFetch: true // 初始化时自动请求 +}; +``` + +## 错误处理 + +```typescript +httpDs.on('change', () => { + if (httpDs.error) { + console.error('请求失败:', httpDs.error.msg); + } else { + console.log('数据:', httpDs.data); + } +}); +``` diff --git a/docs/runtime-api/data-source/observedData.md b/docs/runtime-api/data-source/observedData.md new file mode 100644 index 00000000..52bd6aeb --- /dev/null +++ b/docs/runtime-api/data-source/observedData.md @@ -0,0 +1,148 @@ +# 观察者数据类 + +`@tmagic/data-source` 提供了三种观察者数据类,用于实现数据的响应式监听。 + +## ObservedData(抽象类) + +所有观察者数据类的抽象基类,定义了统一的接口。 + +### 抽象方法 + +| 方法 | 参数 | 返回值 | 说明 | +|------|------|--------|------| +| `update` | `(data: any, path?: string)` | `void` | 更新数据 | +| `on` | `(path: string, callback: Function, options?: { immediate?: boolean })` | `void` | 监听数据变化 | +| `off` | `(path: string, callback: Function)` | `void` | 取消监听 | +| `getData` | `(path: string)` | `any` | 获取指定路径的数据 | +| `destroy` | `()` | `void` | 销毁 | + +## SimpleObservedData + +基于 EventEmitter 的简单观察者实现,只支持单层路径监听。 + +### 使用示例 + +```typescript +import { SimpleObservedData } from '@tmagic/data-source'; + +const observed = new SimpleObservedData({ name: 'test' }); + +// 监听数据变化 +observed.on('name', (newVal) => { + console.log('name 变更为:', newVal); +}); + +// 更新数据 +observed.update({ name: 'new name' }); + +// 更新特定路径 +observed.update('another name', 'name'); + +// 获取数据 +const name = observed.getData('name'); + +// 取消监听 +observed.off('name', callback); + +// 销毁 +observed.destroy(); +``` + +### 特点 + +- 轻量级实现 +- 只支持单层路径监听(如 `'name'`,不支持 `'user.name'`) +- 适用于简单数据结构 + +## DeepObservedData + +基于 `deep-state-observer` 的深度观察者实现,支持深层路径监听。 + +### 使用示例 + +```typescript +import { DeepObservedData } from '@tmagic/data-source'; + +const observed = new DeepObservedData({ + user: { + name: 'test', + profile: { + avatar: 'url' + } + } +}); + +// 监听深层路径 +observed.on('user.profile.avatar', (newVal) => { + console.log('头像变更为:', newVal); +}); + +// 监听整个对象 +observed.on('user', (newVal) => { + console.log('user 对象变更:', newVal); +}); + +// 立即执行回调 +observed.on('user.name', callback, { immediate: true }); + +// 更新深层数据 +observed.update('new avatar', 'user.profile.avatar'); + +// 获取深层数据 +const avatar = observed.getData('user.profile.avatar'); +``` + +### 特点 + +- 支持深层路径监听(如 `'user.profile.avatar'`) +- 支持 `immediate` 选项立即执行回调 +- 适用于复杂嵌套数据结构 +- 性能更优,只在相关路径变化时触发回调 + +## 在 DataSourceManager 中注册 + +可以通过静态方法注册自定义的观察者数据类: + +```typescript +import { DataSourceManager, DeepObservedData } from '@tmagic/data-source'; + +// 注册深度观察者类 +DataSourceManager.registerObservedData(DeepObservedData); +``` + +## 自定义观察者类 + +可以继承 `ObservedData` 实现自定义的观察者类: + +```typescript +import { ObservedData } from '@tmagic/data-source'; + +class CustomObservedData extends ObservedData { + private data: any; + + constructor(data: any) { + super(); + this.data = data; + } + + update(data: any, path?: string): void { + // 自定义更新逻辑 + } + + on(path: string, callback: Function, options?: { immediate?: boolean }): void { + // 自定义监听逻辑 + } + + off(path: string, callback: Function): void { + // 自定义取消监听逻辑 + } + + getData(path: string): any { + // 自定义获取数据逻辑 + } + + destroy(): void { + // 自定义销毁逻辑 + } +} +``` diff --git a/docs/runtime-api/data-source/utils.md b/docs/runtime-api/data-source/utils.md new file mode 100644 index 00000000..455b36c3 --- /dev/null +++ b/docs/runtime-api/data-source/utils.md @@ -0,0 +1,200 @@ +# 工具函数 + +`@tmagic/data-source` 导出的工具函数。 + +## createDataSourceManager + +- **参数:** + - `{TMagicApp} app` 应用实例 + - `{boolean} useMock` 是否使用 Mock 数据(可选) + - `{DataSourceManagerData} initialData` 初始数据(可选) + +- **返回:** + - `{DataSourceManager}` 数据源管理器实例 + +- **详情:** + + 创建数据源管理器的工厂函数,会自动设置数据变化监听。 + +- **示例:** + +```typescript +import { createDataSourceManager } from '@tmagic/data-source'; + +const dsManager = createDataSourceManager(app, false, initialData); +``` + +## compiledCondition + +- **参数:** + - `{CondItem} cond` 条件项 + - `{object} data` 数据上下文 + +- **返回:** + - `{boolean}` 条件是否满足 + +- **详情:** + + 编译单个显示条件。 + +- **示例:** + +```typescript +import { compiledCondition } from '@tmagic/data-source'; + +const result = compiledCondition( + { field: 'user.age', op: '>', value: 18 }, + { user: { age: 20 } } +); +console.log(result); // true +``` + +## compliedConditions + +- **参数:** + - `{MNode} node` 节点配置 + - `{object} data` 数据上下文(可选) + +- **返回:** + - `{boolean}` 节点是否应该显示 + +- **详情:** + + 编译条件组,支持 AND/OR 逻辑。 + +## compiledNodeField + +- **参数:** + - `{any} value` 字段值 + - `{object} data` 数据上下文 + +- **返回:** + - `{any}` 编译后的值 + +- **详情:** + + 编译节点字段中的数据源配置。 + +- **示例:** + +```typescript +import { compiledNodeField } from '@tmagic/data-source'; + +const compiled = compiledNodeField( + { isBindDataSource: true, dataSourceId: 'ds_1', template: '${name}' }, + { ds_1: { name: 'test' } } +); +``` + +## compliedDataSourceField + +- **参数:** + - `{any} value` 字段值 + - `{object} data` 数据上下文 + +- **返回:** + - `{any}` 编译后的值 + +- **详情:** + + 编译数据源字段选择器的值。 + +## template + +- **参数:** + - `{string} value` 模板字符串 + - `{object} data` 数据上下文 + +- **返回:** + - `{string}` 替换后的字符串 + +- **详情:** + + 模板字符串替换,支持 `${id.field}` 格式。 + +- **示例:** + +```typescript +import { template } from '@tmagic/data-source'; + +const result = template( + '用户名:${ds_1.user.name},年龄:${ds_1.user.age}', + { ds_1: { user: { name: '张三', age: 20 } } } +); +console.log(result); // '用户名:张三,年龄:20' +``` + +## createIteratorContentData + +- **参数:** + - `{object} itemData` 迭代项数据 + - `{string} dsId` 数据源 ID + - `{DataSchema[]} fields` 字段配置 + - `{object} dsData` 数据源数据 + +- **返回:** + - `{object}` 迭代器数据上下文 + +- **详情:** + + 创建迭代器的数据上下文。 + +## compliedIteratorItem + +- **参数:** + - `{object} options` 编译选项 + +- **返回:** + - `{MNode}` 编译后的节点 + +- **详情:** + + 编译迭代器项。 + +## updateNode + +- **参数:** + - `{MNode} node` 节点配置 + - `{MApp} dsl` DSL 配置 + +- **返回:** + - `{MApp}` 更新后的 DSL + +- **详情:** + + 更新 DSL 中的指定节点。 + +- **示例:** + +```typescript +import { updateNode } from '@tmagic/data-source'; + +const newDsl = updateNode( + { id: 'button_1', type: 'button', text: '新文本' }, + dsl +); +``` + +## registerDataSourceOnDemand + +- **参数:** + - `{MApp} dsl` DSL 配置 + - `{Record Promise>} modules` 数据源模块映射 + +- **返回:** + - `{Promise}` + +- **详情:** + + 按需加载数据源模块。根据 DSL 中使用的数据源类型动态加载对应模块。 + +- **示例:** + +```typescript +import { registerDataSourceOnDemand } from '@tmagic/data-source'; + +await registerDataSourceOnDemand(dsl, { + custom: () => import('./CustomDataSource'), + socket: () => import('./SocketDataSource') +}); +``` diff --git a/packages/core/src/type.ts b/packages/core/src/type.ts index ac6449d9..b04e0167 100644 --- a/packages/core/src/type.ts +++ b/packages/core/src/type.ts @@ -1,4 +1,4 @@ -import type { DataSource, DataSourceManagerData, ObservedDataClass } from '@tmagic/data-source'; +import type { DataSource, DataSourceManagerData } from '@tmagic/data-source'; import type { DataSourceSchema, EventConfig, Id, JsEngine, MApp, RequestFunction } from '@tmagic/schema'; import type Env from './Env'; @@ -24,7 +24,6 @@ export interface AppOptionsConfig { iteratorContainerType?: string | string[]; transformStyle?: (style: Record) => Record; request?: RequestFunction; - DataSourceObservedData?: ObservedDataClass; dataSourceManagerInitialData?: DataSourceManagerData; nodeStoreInitialData?: () => any; errorHandler?: ErrorHandler;