【概念讲解】
【基础准备】
- 使用 cli 创建 TinyEngine 低代码平台工程
npx @opentiny/tiny-engine-cli@latest create-platform my-designer。 - 创建插件存放目录
mkdir -p src/plugins。(或者手动创建文件夹)。 - 使用 cli 创建新插件:
npx @opentiny/tiny-engine-cli@latest create-plugin custom-gen-code。 - 由于这里我们不需要将插件独立成一个 npm 包,所以我们可以删除生成的插件的无关文件:
package.json、vite.config.js、README.md。 - 安装依赖
pnpm install。 - 按照前面的视频或者文档教程,完成后端工程的启动。
- 启动前端工程:
pnpm serve:frontend。 - 修改
registry.js文件,将新增的插件,增加到注册表中。 - 修改
src/plugins/custom-gen-code/src/Main.vue文件,完成出码基础出码 UI 的编写。
【页面出码实操】 前置动作:创建一个页面,并添加拖拽若干组件。
- 获取当前页面 Or 区块 Schema。
- 调用出码元服务,得到页面出码。
- 根据自身业务需求场景,进行页面代码下载、上传等等动作。
重点知识讲解:
- 出码元服务:
getMetaApi(META_SERVICE.GenerateCode)
该元服务是对 @opentiny/tiny-engine-dsl-vue package 元服务封装。
暴露了以下 api:
parseRequiredBlocks。解析页面依赖的区块。getAllNestedBlocksSchema。循环解析页面依赖的区块。比如页面A依赖了区块B,区块B依赖了区块C等场景。(内部也是调用了parseRequiredBlocks方法)generatePageCode。生成页面代码generateAppCode。生成页面代码
generatePageCode方法解析:
interface IComponentMapItem {
componentName: string
destructuring: boolean
exportName?: string
package?: string
version: string
}
function generatePageCode(
// 页面 schema
schema: IPageSchema,
// 三方组件映射表
componentsMap: Array<IComponentMapItem>,
// 配置项:支持非常多的页面出码定制配置项
config: Record<string, any>
): string;
export interface IPageSchema {
componentName: 'Page' | 'Block'
css: string
fileName: string
lifeCycles: {
[key: string]: Record<string, IFuncType>
}
methods: Record<string, IFuncType>
props: Record<string, any>
state: Array<Record<string, any>>
meta: {
id: number
isHome: boolean
parentId: string
rootElement: string
route: string
}
children: Array<ISchemaChildrenItem>
schema?: {
properties: Array<Record<string, any>>
events: Record<string, any>
}
}【应用出码实操】
- 获取所有页面 schema
- 获取所有区块 schema
- 获取应用信息
- 组装应用信息
- 调用
generateAppCode方法,得到应用代码。 - 处理出码结果
- 根据自身应用业务场景需求,将出码写入到本地、或者是下载 zip 压缩包、或者是上传到后端等等。
重点知识讲解:
generateAppCode方法解析:
const generateAppCode = async (
// 应用 schema
appSchema: IAppSchema,
// 出码配置项
options: IConfig
): Promise<ICodeGenResult>
interface IAppSchema {
i18n: {
en_US: Record<string, any>
zh_CN: Record<string, any>
}
utils: Array<IUtilsItem>
dataSource: IDataSource
globalState: Array<IGlobalStateItem>
pageSchema: Array<IPageSchema | IFolderItem>
blockSchema: Array<IPageSchema>
componentsMap: Array<IComponentMapItem>
meta: IMetaInfo
}
interface IConfig {
// 替换官方的插件,或者是传入新增的插件。
customPlugins?: {
[key in defaultPlugins]?: IPluginFun
} & {
[key in 'transformStart' | 'transform' | 'transformEnd']?: Array<IPluginFun>
}
// 对官方插件传入配置
pluginConfig?: {
[k in defaultPlugins]: Record<string, any>
}
// 传入自定义的出码上下文,出码插件可以获取
customContext?: Record<string, any>
}
// 出码结果返回
interface ICodeGenResult {
// 出码报错信息
errors: Array<any>
// 出码结果
genResult: Array<IFile>
// 出码日志
genLogs: Array<any>
}
// 出码文件
interface IFile {
// 文件类型 js、vue、json、html、md 等等
fileType: string
// 文件名称
fileName: string
// 文件路径
path: string
// 文件内容
fileContent: string
}getAllNestedBlocksSchema方法解析: 循环获取所有依赖的区块,返回他们的 schema,用于出码
const getAllNestedBlocksSchema = async (
pageSchema: IPageSchema,
fetchBlockSchemaApi: (blockName: string) => Promise<IPageSchema>,
blockSet = new Set<string>()
): Promise<IPageSchema[]>【出码定制实践】 示例1: 默认出码。
示例2: 使用官方插件出码配置,自定义出码 prettier 配置。
重点知识讲解:
示例3: 使用官方插件出码配置,替换基础模板工程。
示例4: 使用官方插件出码配置,支持 v-xxx 指令。
示例5: 使用官方插件出码配置,出码解析自定义组件协议。
示例6: 使用官方插件出码配置,替换官方插件实现:自定义方法类型的 utils 为 function 类型。
示例7: 新增插件,对出码进行处理,匹配您的业务逻辑。