如果你在项目中用过阿里低代码引擎,或尝试在项目中使用,那么你或许就会有这样的想法:能不能像前端框架中封装的公共组件一样,拖拽配置出来一个组件公用?而不是每次需要新的公共组件的时候,都要按照官方文档,去重新新建一个项目,按照文档说明去配置去开发,最后再打包引入到原工程。
基于上面的场景,笔者通过一个鬼点子实现了该功能,当前实现的方案不支持出码模块。
演示地址:www.zzusp.asia (备) http://124.222.119.198/
注:阅读本篇文章需要对低代码引擎有一定的了解,如:渲染、appHelper、低代码组件开发
先说下整体思路
- 在原项目中实现
渲染模块
的逻辑,传入页面的code可以渲染对应页面(其实就是根据code获取对应的schema,然后动态渲染) - 将渲染模块作为一个
渲染方法
的返回值,通过appHelper
传入引擎中 - 新建项目,开发一个用于接收动态渲染的低代码组件(
渲染组件
),并配置到引擎的组件库中 - 拖拽
渲染组件
,并在引擎源码面板中,将渲染方法
与渲染组件
绑定即可
1. 渲染模块代码
js
<Renderer page={page} />
展开查看代码
js
import React, {useState, useEffect} from 'react';
import {Loading} from '@alifd/next';
import mergeWith from 'lodash/mergeWith';
import isArray from 'lodash/isArray';
import {buildComponents, assetBundle, AssetLevel, AssetLoader} from '@alilc/lowcode-utils';
import ReactRenderer from '@alilc/lowcode-react-renderer';
import {injectComponents} from '@alilc/lowcode-plugin-inject';
import appHelper from '../../appHelper';
import {
getProjectSchemaFromDb,
getPackagesFromAssets
} from '../../services/schemaService';
const Renderer = (props) => {
const {page} = props;
const [data, setData] = useState({});
useEffect(() => {
setData({});
init();
}, [page])
async function init() {
console.log('Renderer Page ' + page);
const projectSchema = await getProjectSchemaFromDb(page);
const packages = await getPackagesFromAssets();
setData({});
const {
componentsMap: componentsMapArray,
componentsTree,
i18n,
dataSource: projectDataSource,
} = projectSchema;
const componentsMap: any = {};
componentsMapArray.forEach((component: any) => {
componentsMap[component.componentName] = component;
});
const pageSchema = 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)];
// TODO asset may cause pollution
const assetLoader = new AssetLoader();
await assetLoader.load(libraryAsset);
const components = await injectComponents(buildComponents(libraryMap, componentsMap));
setData({
schema: pageSchema,
components,
i18n,
projectDataSource,
});
}
const {schema, components, i18n = {}, projectDataSource = {}} = data as any;
if (!schema) {
return <Loading fullScreen tip={<span style={{color: '#5584ff'}}>Loading...</span>}>
<div className="lowcode-plugin-sample-preview" style={{ minHeight : '90vh' }}></div>
</Loading>;
}
function customizer(objValue: [], srcValue: []) {
if (isArray(objValue)) {
return objValue.concat(srcValue || []);
}
}
return (
<div className="lowcode-plugin-sample-preview" style={{ minHeight : '90vh' }}>
{!schema ? <Loading style={{ width : '100%', height : '90vh' }}/> : <ReactRenderer
className="lowcode-plugin-sample-preview-content"
style={{ height : '100%' }}
schema={{
...schema,
dataSource: mergeWith(schema.dataSource, projectDataSource, customizer),
}}
components={components}
messages={i18n}
appHelper={appHelper}
/>
}
</div>
);
};
export default Renderer;
2. 通过appHelper将渲染传入引擎
js
appHelper.utils.renderer = (page) => {
return <Renderer page={page} />
};
3. 实现低代码组件-渲染组件
shell
# 新建一个低代码组件项目并启动
npm init @alilc/element your-element-name
cd your-element-name
npm install
npm start
渲染组件核心代码index.tsx
js
import * as React from 'react';
interface ComponentProps {
name: string,
element: any,
onRender: Function|undefined
}
export default class CustomRendererComponent extends React.Component<ComponentProps> {
constructor(props) {
super(props);
this.state = {
name: props.name,
element: props.element,
onRender: props.onRender
};
this.ref = React.createRef();
}
componentDidMount() {
if (this.state.onRender !== undefined) {
this.state.onRender(this.ref);
}
}
render() {
return (
<div className="CustomRendererComponent">
<div ref={this.ref}>
{this.state.element || 'no element'}
</div>
</div>
)
}
}
引入到原项目
js
打包新建的低代码组件项目,通过本地拷贝也好,发布到npm仓库再install也好,将低代码组件的资源引入到原项目中。这部分阅读下官方文档,这里就不详细说明了。
然后修改原项目中的assets.json,将低代码组件配置到引擎中,现在在组件库面板
{
"packages": [
...
],
"components": [
...
{
"exportName": "PluginCustomRendererMeta",
"npm": {
"package": "plugin-custom-renderer",
"version": "0.1.0"
},
"url": "./lowcode/meta.js",
"urls": {
"default": "./lowcode/meta.js"
},
"advancedUrls": {
"default": [
"./lowcode/meta.js"
]
}
}
],
"sort": {
"groupList": [
"精选组件",
"原子组件",
"低代码组件"
],
"categoryList": [
"基础元素",
"布局容器类",
"表格类",
"表单详情类",
"帮助类",
"对话框类",
"业务类",
"通用",
"导航",
"引导",
"信息输入",
"信息展示",
"信息反馈",
"常用"
]
},
"groupList": [
"精选组件",
"原子组件",
"低代码组件"
],
"ignoreComponents": {}
}
启动后就可以在组件面板中看到我们新建的低代码渲染组件了,如下图:
4. 配置低代码渲染组件
按照下图的三步配置后,就可以渲染其他已经配置好的页面
(图中的dashboard是配置好的首页的code)
结语
- 该方案还不支持出码模块,根据官方文档重新开发出码模块是否能够达到预期效果未知
- 还未实现传参,但有可行方案,如:通过appHelper
- 该方案只是出于兴趣,如要使用到实际项目中,还望慎重
本文正在参加阿里低代码引擎征文活动