1
0
mirror of synced 2026-02-04 18:47:57 +08:00

docs: 完善组件开发/runtime/表单配置文档

This commit is contained in:
roymondchen
2026-01-26 19:06:39 +08:00
parent 450af8021d
commit c23d02558e
35 changed files with 1610 additions and 255 deletions

View File

@@ -83,30 +83,29 @@ export default {
</template>
<script lang="ts" setup>
import { defineComponent, inject } from 'vue';
import { type ComponentProps, registerNodeHooks, useApp } from '@tmagic/vue-runtime-help';
const props = defineProps({
config: {
type: Object,
default: () => ({}),
},
})
const props = defineProps<ComponentProps>()
const app: Core | undefined = inject('app');
const node = app?.page?.getNode(props.config.id);
const { app, node } = useApp(props);
const onClick = () => {
// app.emit 第一个参数为事件名,其余参数为你要传给接受事件组件的参数
app?.emit("yourComponent:finishSomething", node, /*可以传参给接收方*/);
app.emit("yourComponent:finishSomething", node, /*可以传参给接收方*/);
};
// 此处实现事件动作
const toast = () => {
toast('测试 vue3')
};
// 实际触发时是调用node上的方法所以需要将改方法暴露到node上
registerNodeHooks(node, {
toast,
});
defineExpose({
// 此处实现事件动作
// 实际触发时是调用vue实例上的方法所以需要将改方法暴露到实例上
toast: (/*触发组件node*/, /*接收触发事件组件传进来的参数*/) => {
toast('测试 vue3')
}
toast,
});
</script>
```
@@ -151,10 +150,3 @@ function Test({ config }) {
export default Test;
```
按照上述实现触发事件和事件动作,就可以完成组件的联动事件分发响应。
:::tip
组件事件的联动是借助了@tmagic/core,需要在组件实例化的时候将需要暴露的方法提供给@tmagic/core在上述例子中useApp方法的调用就是完成这个操作useApp返回的app对象就是@tmagic/core的实例。在vue的实现中useApp是将整个vue实例都提供给了app所以需要defineExpose来定义vue instance上的方法react则是将需要暴露的方法作为useApp的参数传入
:::

View File

@@ -1,28 +1,27 @@
# 如何开发一个组件
tmagic-editor支持业务方进行自定义组件开发。在tmagic-editor中组件是以 npm 包形式存在的组件和插件只要按照规范开发就可以在tmagic-editor的 runtime 中被加入并正确渲染组件。
## 组件开发
以 vue 的组件开发为例。运行项目中的 playground 示例,会自动加载 vue 的 runtime。runtime会加载[@tmagic/ui](https://github.com/Tencent/tmagic-editor/tree/master/packages/ui)
## 组件注册
在 [playground](https://tencent.github.io/tmagic-editor/playground/index.html#/) 中,我们可以尝试点击添加一个组件,在模拟器区域里,就会出现这个组件。其中就涉及到组件注册。
这一步需要开发者基于tmagic-editor搭建了平台后实现组件列表的注册、获取机制tmagic-editor组件注册其实就是保存好组件 `type` 的映射关系。`type` 可以参考[组件介绍](../guide/conception.html#组件)。
可以参考 vue 版本的 @tmagic/ui 中,[组件渲染](../guide/advanced/page.html#组件渲染)逻辑里type 会作为组件名进入渲染。所以在 vue 的组件开发中,我们也需要在为 vue 组件声明 name 字段时,和 type 值对应起来,才能正确渲染组件。
### 组件规范
组件的基础形式,需要有四个文件
- index 入口文件,引入下面几个文件
- formConfig 表单配置描述
- initValue 表单初始值
- form-config 表单配置描述
- init-value 表单初始值
- event 定义联动事件,具体可以参考[组件联动](../guide/advanced/coupling.html#组件联动)
- component.{vue,jsx} 组件样式、逻辑代码
@tmagic/ui 中的 button/text 就是基础的组件示例。我们要求声明 index 入口,因为我们希望在后续的配套打包工具实现上,可以有一个统一规范入口。
### 1. 创建组件
在项目中,如 runtime 目录中,创建一个名为 test-component 的组件目录,其中包含上面四个规范文件。
可以使用`npm create tmagic` 选择 `components:组件库(组件/插件/数据源)` 来快速创建一个组件库。
然后继续使用`npm create tmagic` 选择 `component:组件` 来快速创建一个组件。
:::tip
组件库并不是必须,组件如何管理可以根据具体情况来选择。直接放到 runtime 目录中也是一个不错的选择如果选择放到runtime中可以在runtime中的package.json添加`"tmagicComponentsPath": "./components"` 来指定组件库的路径。这样在使用`npm create tmagic` 来创建组件时,会自动将组件添加到组件库中。
:::
手动创建组件,可以在项目中,如 runtime 目录中,创建一个名为 test-component 的组件目录,其中包含上面四个规范文件。
```javascript
// index.js
// vue
@@ -30,14 +29,18 @@ import Test from './Test.vue';
// react
import Test from './Test.tsx';
export { default as config } from './formConfig';
export { default as value } from './initValue';
export { default as config } from './form-config';
export { default as value } from './init-value';
export default Test;
```
:::tip
如果在runtime中使用了@tmagic/cli,则必须保持此规范;不使用则可以自由书写。
:::
```javascript
// formConfig.js
// form-config.js
export default [
{
type: 'select',
@@ -61,15 +64,40 @@ export default [
];
```
:::tip
配置内容必须是一个数组,每个元素是一个对象,包含 type、text、name 等属性,每个对象代表一个表单项。
type 是表单项的类型
text 是表单项的文本
name 是表单项值的key。
上述实例对应生成的值为
```json
{
"color": "red",
"text": "一段文字",
}
```
type 在@tmagic/form@tmagic/editor 中默认提供了种,@tmagic/form提供的可以前往[表单配置](/form-config/fields/text.html)查看。
:::
```javascript
// initValue.js
// init-value.js
export default {
color: 'red',
text: '一段文字',
};
```
版本的组件代码示例
:::tip
在编辑器中添加组件时使用,作为初始值。
:::
Vue版本的组件代码示例
```vue
<!-- Test.vue -->
<template>
@@ -79,22 +107,24 @@ export default {
</div>
</template>
<script>
export default {
<script setup>
defineOptions({
name: 'magic-ui-test',
});
props: {
config: {
type: Object,
default: () => ({}),
},
defineProps({
config: {
type: Object,
default: () => ({}),
},
setup() {},
};
}):
</script>
```
:::tip
编辑器中配置的 config 对象,会作为 props 传入组件中。
:::
react 版本组件代码示例
```javascript
// Test.tsx
@@ -118,84 +148,52 @@ export default Test;
```
### 2. 使用tmagic-cli
在 runtime vue 中,我们已经提供好一份示例。在 tmagic.config.ts 文件中。只需要在 packages 加入你创建的组件的路径(如果是个 npm 包,则将路径替换为包名即可),打包工具就会自动识别到你的组件
## 插件开发
插件开发和组件开发形式类似,但是插件开发不需要有组件的规范
我们只需要在插件中提供一个入口文件。插件需要提供一个 install 方法。
### 3. 启动 playground
在上面的步骤完成后,在 playground/src/configs/componentGroupList 中。找到组件栏的基础组件列表,在其中加入你的开发组件
```javascript
{
title: '基础组件',
items: [
// 在Vue的runtime中
export default {
install(vueApp, { app: tmagicApp }) {}
}
```
```javascript
// 在React的runtime中
export default {
install({ app: tmagicApp }) {}
}
```
在插件中开发者可以自由实现需要的业务逻辑。
## 集成到runtime中
### 使用@tmagic/cli
在使用`npm create tmagic` 创建的runtime中自动集成了@tmagic/cli将组件集成到此runtime中只需要在`tmagic.config.ts`中的packages字段中添加
```javascript
import { defineConfig } from '@tmagic/cli';
export default defineConfig({
// other config
packages: [
{
text: '文本',
type: 'text',
},
{
text: '按钮',
type: 'button',
},
// 加入这个测试组件
{
text: '测试',
type: 'test',
'组件type': '组件目录或者npm包名',
},
],
}
```
然后,在 magic 项目根目录中,运行
});
```
npm run playground
```
至此,我们打开 playground 后,就能添加开发的中的组件,并且得到这个开发中的组件**在编辑器中的表现**了。
:::tip
组件type需要与[componentGroupList](../api/editor/props.html#componentgrouplist)中的type对应。
:::
<img src="https://image.video.qpic.cn/oa_fd3c9c-3_548108267_1636719045199471">
### 4. 启动 runtime
在完成开发中组件在编辑器中的实现后,我们将编辑器中的 DSL 源码📄 打开,复制 DSL。并在 runtime/vue/src/page 下。创建一个 page-config.js 文件。将 DSL 作为配置导出。
配置到packages字段中后执行`npm run tmagic`来创建组件库的入口文件。
```javascript
window.magicDSL = [
// DSL
]
```
然后使用`npm run build:libs`命令来构建用于编辑器中的组件配置、组件初始值、组件事件联动的资源文件。
在 page/main.ts 中,将这份配置读入
```javascript
import './page-config.js';
```
然后执行在 runtime/ 目录下执行
```
npm run build:libs
npm run dev
```
至此,我们就可以得到这个开发中组件在编辑器中进行了配置并保存后,在真实页面中应该有的样子。
<img src="https://image.video.qpic.cn/oa_fd3c9c-3_1731965034_1636719708671597?imageView2/q/70" width="50%">
## 插件开发
插件开发和组件开发形式类似,但是插件开发不需要有组件的规范。在以 vue 为基础的 ui 和 runtime 中,插件其实就是一个 vue 插件。
我们只需要在插件中提供一个入口文件,其中包含 vue 的 install 方法即可。
```javascript
export default {
install() {}
}
```
在插件中开发者可以自由实现需要的业务逻辑。插件和组件一样,只需要在 units.js 中,加入导出的 units 对象里即可。
## 业务定制
上述的步骤,如
1. 组件/插件初始化
2. 编辑器中的组件调试
3. 真实页面的组件调试
4. 编辑器中的 DSL 同步至本地调试页面
等许多步骤,都可以交由业务方进行定制,开发业务自定义的脚手架工具,或者如示例中一样,使用打包脚本来处理。

View File

@@ -195,6 +195,9 @@ npm install sass -D
## runtimeUrl
该配置涉及到 [runtime 概念](runtime.md)tmagic-editor编辑器中心的模拟器画布是一个 iframe这里的 `runtimeUrl` 配置的,就是你提供的 iframe 的 url其中渲染了一个 runtime用来响应编辑器中的组件增删改等操作。
:::tip
可以使用`npm create tmagic` 来快速创建一个runtime项目。
:::
## componentGroupList

View File

@@ -1,70 +1,29 @@
# RUNTIME
本章详细介绍如何深入理解tmagic-editor的打包以及如何根据需求定制修改tmagic-editor的页面打包发布方案。页面发布、打包相关的定制化开发需要使用tmagic-editor的业务方搭建好基于开源tmagic-editor的管理平台、存储服务等配套设施。
## runtime 是什么
runtime是用来解析DSL的执行环境用于渲染 DSL 呈现页面。
编辑器生成出来的DSL需要通过 runtime 来渲染。
## 实现一个 runtime
在 [@tmagic/ui](./advanced/tmagic-ui.html) 部分我们已经说过runtime 和 UI 是配套实现的。每个版本的 runtime 都需要一个对应的 UI 来作为渲染器,实现渲染 DSL 呈现页面的功能。
### UI
一个 UI 应该至少包含一个渲染器,来实现[页面渲染](./advanced/page.html)。同时可以提供一些基础组件。具体实现可以参考[@tmagic/ui](./advanced/tmagic-ui.html)。
:::tip
可以使用`npm create tmagic` 来快速创建一个runtime项目
:::
### page
runtime 的 `page` 部分,就是真实项目页面的渲染环境。发布出去的项目页都需要基于该部分来实现渲染功能。而 `page` 的主要逻辑,就是需要加载 UI同时实现业务方需要的业务逻辑比如
- 提供页面需要的全局 api
- 业务需要的特殊实现逻辑
- 加载第三方全局组件/插件等
具体的 page 实现示例,可以参考
- [vue runtime](https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue/page)
- [react runtime](https://github.com/Tencent/tmagic-editor/blob/master/runtime/react/page)
### playground
runtime 的 `playground` 部分,和 `page` 做的事情几乎一致,业务方可以包含上述 `page` 所拥有的全部能力。但是,因为 playground 需要被编辑器加载,作为编辑器中页面模拟器的渲染容器,和编辑器通信,接受编辑器中组件的增删改查。所以,除了保持和 `page` 一样的渲染逻辑之外,`playground` 还要额外实现一套既定通信内容和 api才能实现和编辑器的通信功能。
#### onRuntimeReady
**在 playground 页面渲染后**,需要调用接口通知编辑器完成加载。该调用需要传入一个参数 API即挂载了增删改查功能的对象示例提供给编辑器。
```javascript
window.magic?.onRuntimeReady(API)
创建出来的项目会包含page、playground两个目录。
```bash
.
├── page
├── playground
```
#### onPageElUpdate
**playground 在每次更新了页面配置后**,调用一次 onPageElUpdate 并传入一个 DOM 节点,该方法作用是传入一个页面渲染组件的根节点,用来告知编辑器的模拟器遮罩如何作出反应。
```javascript
window.magic.onPageElUpdate(document.querySelector('.magic-ui-page'));
```
page用于生产环境
#### 提供 API
| API | 说明 | 参数 |
|---------- |-------- |---------- |
|updateRootConfig| 根节点更新 | `root: MApp` |
|updatePageId| 更新当前页面 id | `id: string` |
|select| 选中组件 | `id: string`|
|add| 增加组件 | { `config` , `root` }: `UpdateData` |
|update| 更新组件 | { `config` , `root` }: `UpdateData` |
|remove| 删除组件 | { `config` , `root` }: `UpdateData` |
|sortNode| 组件在容器间排序 |{ `src` , `dist`, `root` }: `SortEventData` |
playground用于编辑器中
runtime 的实现示例可以参考tmagic-editor提供的
- [vue runtime](https://github.com/Tencent/tmagic-editor/blob/master/runtime/vue)
- [react runtime](https://github.com/Tencent/tmagic-editor/blob/master/runtime/react)
### 页面发布
如介绍中提到的tmagic-editor页面发布方案是对构建产物 `page/index.html` 进行项目信息注入。项目信息就是搭建平台存储的页面配置。发布时,将注入项目信息的 `page/index.html` 发布出去即可。
## 版本管理
基于上一步提到的打包原理,每次构建后,得到的产物都可以进行归档编号,存为版本。涉及到的组件改动和新增修改,体现在各个版本中。
<img src="https://image.video.qpic.cn/oa_88b7d-32_1233288257_1633783105283986" width="40%" alt="版本选择">
版本管理具体如何实现这取决于使用tmagic-editor的业务方。版本管理具有如下优点
1. 对于已经配置好发布的项目,使用固定版本,不会被新版本的特性影响,保证项目线上稳定运行
2. 发布的新版本如果出现问题,可以及时回退选择使用旧版本
## 结合业务定制
tmagic-editor的静态资源构建项目配置保存页面发布在tmagic-editor的提供的示例方案中流程是
1. 触发构建,执行流水线,基于 runtime 执行 build
2. 将构建产物归档推送至 cdn存为一个ui版本
3. 项目配保存后,项目发布时,将项目配置发布至 CDN 存储为 DSL.js同时根据当前项目使用的ui版本获取到 page/index.html将 DSL.js 引用方式以 script 标签形式写入。
4. 将注入信息的 page/index.html 发布为项目静态资源 act.html
5. 线上可加载 act.html 访问项目
其中各个步骤的定制可以交由业务方根据tmagic-editor提供的示例进行自定义修改。
:::tip
想要了解DSL的解析以及runtime与编辑器的通信可以前往[教程](/guide/tutorial/index.md)
:::