如何用 ReactRenderer 在 React 项目中渲染 lowcode-engine 设计器产出的页面 schema
【免费下载链接】lowcode-engineAn enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系项目地址: https://gitcode.com/GitHub_Trending/lo/lowcode-engine
lowcode-engine 的设计器搭建完成后会产出两份数据:资产包数据 assets 和页面数据 schema。如果你的目标是把设计器产出的页面在自己的 React 项目中跑起来(而不是出码成独立工程),官方提供的是 React 渲染模块@alilc/lowcode-react-renderer(即 ReactRenderer)。本文按官方文档给出的完整路径,说明如何从设计器导出数据、在预览页加载并转换成 ReactRenderer 所需的两个 prop,最后完成渲染与结果判断。该渲染模块基于 React 实现,Vue 形态不在其支持范围内(文档提示见 接入运行时)。
渲染的两个必选输入:schema 与 components
渲染模块的运行只依赖两份必选数据,且两者必须一一对应:
schema:符合低代码搭建协议的数据,渲染模块基于其中内容实时渲染;components:组件依赖的实例对象,其中 Key 需要和 schema 中的componentName字段对应。
schema 中使用到的组件如果都未在components中声明,页面无法正常渲染——这是后面所有步骤的核心约束。
最小用法是这样的:手写一份 schema,把组件实例传给 ReactRenderer:
import ReactRenderer from '@alilc/lowcode-react-renderer'; import ReactDOM from 'react-dom'; import { Button } from '@alifd/next'; const schema = { componentName: 'Page', props: {}, children: [ { componentName: 'Button', props: { type: 'primary', style: { color: '#2077ff' }, }, children: '确定', }, ], }; const components = { Button, }; ReactDOM.render(( <ReactRenderer schema={schema} components={components} /> ), document.getElementById('root'));渲染结果就是一个 primary 样式的"确定"按钮。示例代码见 使用渲染模块。
渲染模块的包信息可以在仓库中核对:packages/react-renderer/package.json(当前版本 1.3.2,依赖@alifd/next与@alilc/lowcode-renderer-core);实现入口为 packages/react-renderer/src/index.ts,它基于@alilc/lowcode-renderer-core的 rendererFactory 注册了 PageRenderer 等渲染器。
注意:接入运行时 正文有一处把包名写作
@alifd/lowcode-react-renderer,但仓库 package.json 与所有示例 import 均为@alilc/lowcode-react-renderer,以后者为准。
设计器产出的数据不能直接作为schema/components传入,需要按下面两步做转换。
第 1 步:在设计器中导出 schema 和资产包
在设计器侧,通过引擎 API 分别拿到资产包和当前页面的 schema:
// 获取资产包数据 import { material, project } from '@alilc/lowcode-engine'; const packages = material.getAssets().packages// 获取当前配置页面的 schema import { material, project } from '@alilc/lowcode-engine'; const schema = project.exportSchema();然后以某种方式持久化这两份数据。文档示例用 localStorage 演示,真实项目中应使用数据库或其他存储:
window.localStorage.setItem( 'projectSchema', JSON.stringify(project.exportSchema()) ); const packages = await filterPackages(material.getAssets().packages); window.localStorage.setItem( 'packages', JSON.stringify(packages) );第 2 步:预览页加载 schema 与 packages
渲染端(独立于设计器的页面)读回这两份数据:
const packages = JSON.parse(window.localStorage.getItem('packages') || ''); const projectSchema = JSON.parse(window.localStorage.getItem('projectSchema') || ''); const { componentsMap: componentsMapArray, componentsTree } = projectSchema;转换规则来自 接入运行时,只有两条:
schema:取projectSchema.componentsTree[0];components:根据projectSchema中声明的componentsMap,加载 packages 中所有依赖的资产包,取资产包实例,生成"物料 - 资产包"的键值对。
第 3 步:把资产包转换成 components,并渲染
官方给出的完整预览组件(示例取自 使用渲染模块,demo-general 的src/preview.tsx中是更完整的版本):
import ReactDOM from 'react-dom'; import React, { useState } from 'react'; import { Loading } from '@alifd/next'; import { buildComponents, assetBundle, AssetLevel, AssetLoader } from '@alilc/lowcode-utils'; import ReactRenderer from '@alilc/lowcode-react-renderer'; import { injectComponents } from '@alilc/lowcode-plugin-inject'; const SamplePreview = () => { const [data, setData] = useState({}); async function init() { // 渲染前置处理,初始化项目 schema 和资产包为渲染模块所需的 schema prop 和 components prop const packages = JSON.parse(window.localStorage.getItem('packages') || ''); const projectSchema = JSON.parse(window.localStorage.getItem('projectSchema') || ''); const { componentsMap: componentsMapArray, componentsTree } = projectSchema; const componentsMap: any = {}; componentsMapArray.forEach((component: any) => { componentsMap[component.componentName] = component; }); const schema = componentsTree[0]; const libraryMap = {}; const libraryAsset = []; packages.forEach(({ package: _package, library, urls, renderUrls }) => { libraryMap[_package] = library; if (renderUrls) { libraryAsset.push(renderUrls); } else if (urls) { libraryAsset.push(urls); } }); const vendors = [assetBundle(libraryAsset, AssetLevel.Library)]; const assetLoader = new AssetLoader(); await assetLoader.load(libraryAsset); const components = await injectComponents(buildComponents(libraryMap, componentsMap)); setData({ schema, components, }); } const { schema, components } = data; if (!schema || !components) { init(); return <Loading fullScreen />; } return ( <div className="lowcode-plugin-sample-preview"> <ReactRenderer className="lowcode-plugin-sample-preview-content" schema={schema} components={components} /> </div> ); }; ReactDOM.render(<SamplePreview />, document.getElementById('ice-container'));几个关键点:
- 资产包按
renderUrls优先、urls兜底取静态资源,加载完成后用buildComponents(libraryMap, componentsMap)生成组件映射,再经injectComponents注入得到最终的components; - 数据未就绪时组件返回
<Loading fullScreen />并触发init(),就绪后才渲染 ReactRenderer; - 代码中的
ice-container是文档示例中挂载节点的 id,替换为你项目里实际的容器元素 id 即可; - 预览页需要引入的依赖即上面代码中的 import:
@alilc/lowcode-react-renderer、@alilc/lowcode-utils、@alilc/lowcode-plugin-inject、@alifd/next与react/react-dom。
渲染结果判断与常用参数
文档没有给出固定的成功日志,判断依据是行为层面的:
- 页面按 schema 中的组件结构渲染出来,说明
schema与components对应关系正确; - 如果某个组件在
components中找不到,渲染模块有对应的"组件未找到"展示,可通过notFoundComponent参数自定义展示文案(类型为 Component,必选参数中不要求,可选); - 若页面使用了国际化,需同时传
locale(如'zh-CN')和messages(各语言的文案对象),格式示例见 使用渲染模块。
除两个必选 prop 外,与渲染页面相关的常用可选参数(完整参数表见 使用渲染模块 的 API 一节):
| 参数 | 说明 | 必选 |
|---|---|---|
| schema | 符合搭建协议的数据 | 是 |
| components | 组件依赖的实例 | 是 |
| componentsMap | 组件的配置信息,生产环境下不需要设置 | 否 |
| appHelper | 渲染模块全局上下文 | 否 |
| designMode | 设计模式,主要在搭建场景使用,生产环境下不需要设置 | 否 |
| suspended | 是否挂起,下钻编辑或多引擎渲染场景使用 | 否 |
| notFoundComponent | 组件找不到时自定义展示文案 | 否 |
| thisRequiredInJSE | 为 true 时 JSExpression 仅支持通过 this 访问,默认 true(版本 >= 1.0.11) | 否 |
| locale / messages | 国际化语言类型与文案对象 | 否 |
appHelper用于把utils(全局公共函数)、constants(全局常量)、react-router 的location/history实例挂到容器组件的 this 上,schema 中的 JSExpression 即可直接使用,例如this.location.pathname或this.utils.xxx(this.constants.yyy),用法示例见文档中的 appHelper 一节。
边界与限制
componentsMap和designMode只服务搭建场景(属性校验、容器占位、选中边框等),生产渲染不需要设置;suspended设为 true 时渲染模块最外层容器的shouldComponentUpdate始终返回 false,用于下钻编辑或多引擎渲染场景;- 官方 demo(lowcode-demo 的 demo-general)右上角提供渲染模块的示例入口,其
src/preview.tsx是本文转换逻辑的更完整版本,可对照阅读; - 渲染和出码是两条消费路径:渲染模块允许后续继续在低代码编辑器中以 LowCode 方式维护,出码模块则生成源码、不再依赖运行时,选型说明见 接入运行时。
【免费下载链接】lowcode-engineAn enterprise-class low-code technology stack with scale-out design / 一套面向扩展设计的企业级低代码技术体系项目地址: https://gitcode.com/GitHub_Trending/lo/lowcode-engine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考