使用渲染模块

快速使用

渲染依赖于 schema 和 components。其中 schema 和 components 需要一一对应,schema 中使用到的组件都需要在 components 中进行声明,否则无法正常渲染。

简单示例

  1. import ReactRenderer from '@alilc/lowcode-react-renderer';
  2. import ReactDOM from 'react-dom';
  3. import { Button } from '@alifd/next';
  4. const schema = {
  5. componentName: 'Page',
  6. props: {},
  7. children: [
  8. {
  9. componentName: 'Button',
  10. props: {
  11. type: 'primary',
  12. style: {
  13. color: '#2077ff'
  14. },
  15. },
  16. children: '确定',
  17. },
  18. ],
  19. };
  20. const components = {
  21. Button,
  22. };
  23. ReactDOM.render((
  24. <ReactRenderer
  25. schema={schema}
  26. components={components}
  27. />
  28. ), document.getElementById('root'));
  • rax-renderer:npm 包替换为 @alilc/lowcode-rax-renderer

项目使用示例

设计器 demo:https://lowcode-engine.cn/demo

项目代码完整示例:https://github.com/alibaba/lowcode-demo

step 1:在设计器中获取组件列表

  1. import { material, project } from '@alilc/lowcode-engine';
  2. const packages = material.getAssets().packages

step 2:在设计器中获取当前配置页面的 schema

  1. import { material, project } from '@alilc/lowcode-engine';
  2. const schema = project.exportSchema();

step 3:以某种方式存储 schema 和 packages

这里用 localStorage 作为存储示例,真实项目中使用数据库或者其他存储方式。

  1. window.localStorage.setItem(
  2. 'projectSchema',
  3. JSON.stringify(project.exportSchema())
  4. );
  5. const packages = await filterPackages(material.getAssets().packages);
  6. window.localStorage.setItem(
  7. 'packages',
  8. JSON.stringify(packages)
  9. );

step 4:预览时,获取存储的 schema 和 packages

  1. const packages = JSON.parse(window.localStorage.getItem('packages') || '');
  2. const projectSchema = JSON.parse(window.localStorage.getItem('projectSchema') || '');
  3. const { componentsMap: componentsMapArray, componentsTree } = projectSchema;

step 5:通过整合 schema 和 packages 信息,进行渲染

  1. import ReactDOM from 'react-dom';
  2. import React, { useState } from 'react';
  3. import { Loading } from '@alifd/next';
  4. import { buildComponents, assetBundle, AssetLevel, AssetLoader } from '@alilc/lowcode-utils';
  5. import ReactRenderer from '@alilc/lowcode-react-renderer';
  6. import { injectComponents } from '@alilc/lowcode-plugin-inject';
  7. const SamplePreview = () => {
  8. const [data, setData] = useState({});
  9. async function init() {
  10. // 渲染前置处理,初始化项目 schema 和资产包为渲染模块所需的 schema prop 和 components prop
  11. const packages = JSON.parse(window.localStorage.getItem('packages') || '');
  12. const projectSchema = JSON.parse(window.localStorage.getItem('projectSchema') || '');
  13. const { componentsMap: componentsMapArray, componentsTree } = projectSchema;
  14. const componentsMap: any = {};
  15. componentsMapArray.forEach((component: any) => {
  16. componentsMap[component.componentName] = component;
  17. });
  18. const schema = componentsTree[0];
  19. const libraryMap = {};
  20. const libraryAsset = [];
  21. packages.forEach(({ package: _package, library, urls, renderUrls }) => {
  22. libraryMap[_package] = library;
  23. if (renderUrls) {
  24. libraryAsset.push(renderUrls);
  25. } else if (urls) {
  26. libraryAsset.push(urls);
  27. }
  28. });
  29. const vendors = [assetBundle(libraryAsset, AssetLevel.Library)];
  30. const assetLoader = new AssetLoader();
  31. await assetLoader.load(libraryAsset);
  32. const components = await injectComponents(buildComponents(libraryMap, componentsMap));
  33. setData({
  34. schema,
  35. components,
  36. });
  37. }
  38. const { schema, components } = data;
  39. if (!schema || !components) {
  40. init();
  41. return <Loading fullScreen />;
  42. }
  43. return (
  44. <div className="lowcode-plugin-sample-preview">
  45. <ReactRenderer
  46. className="lowcode-plugin-sample-preview-content"
  47. schema={schema}
  48. components={components}
  49. />
  50. </div>
  51. );
  52. };
  53. ReactDOM.render(<SamplePreview />, document.getElementById('ice-container'));

API

参数

说明

类型

必选

schema

符合搭建协议的数据

Object

components

组件依赖的实例

Object

componentsMap

组件的配置信息

Object

appHelper

渲染模块全局上下文

Object

designMode

设计模式,可选值:extend、border、preview

String

suspended

是否挂起

Boolean

onCompGetRef

组件 ref 回调(schema, ref)=> {}

Function

onCompGetCtx

组件 ctx 更新回调 (schema, ctx) => {}

Function

rendererName

渲染类型,标识当前模块是以什么类型进行渲染的

string

customCreateElement

自定义创建 element 的钩子

(Component, props, children) => {}

Function

schema

搭建基础协议数据,渲染模块将基于 schema 中的内容进行实时渲染。

components

渲染模块渲染页面需要用到的组件依赖的实例,components 对象中的 Key 需要和搭建 schema 中的componentName 字段对应。

componentsMap

在生产环境下不需要设置。

配置规范参见《低代码引擎搭建协议规范》,主要在搭建场景中使用,用于提升用户搭建体验。

  • 属性配置校验:用户可以配置组件特定属性的 propTypes,在搭建场景中用户输入的属性值不满足 propType 配置时,渲染模块会将当前属性设置为 undefined,避免组件抛错导致编辑器崩溃;
  • isContainer 标记:当组件被设置为容器组件且当前容器组件内没有其他组件时,用户可以通过拖拽方式将组件直接添加到容器组件内部;
  • parentRule 校验:当用户使用的组件未出现在组件配置的 parentRule 组件内部时,渲染模块会使用 visualDom 组件进行占位,避免组件抛错的同时在下钻编辑场景也能够不阻塞用户配置,典型的场景如Step.ItemTable.ColumnTab.Item 等等。

appHelper

appHelper 主要用于设置渲染模块的全局上下文,目前 appHelper 支持设置以下上下文:

  • utils:全局公共函数
  • constants:全局常量
  • location:react-router 的 location 实例
  • history:react-router 的 history 实例

设置了 appHelper 以后,上下文会直接挂载到容器组件的 this 上,用户可以在搭建协议中的 function 及变量表达式场景使用上下文,具体使用方式如下所示:

schema:

  1. export default {
  2. "componentName": "Page",
  3. "fileName": "test",
  4. "props": {},
  5. "children": [{
  6. "componentName": "Div",
  7. "props": {},
  8. "children": [{
  9. "componentName": "Text",
  10. "props": {
  11. "text": {
  12. "type": "JSExpression",
  13. "value": "this.location.pathname"
  14. }
  15. }
  16. }, {
  17. "componentName": "Button",
  18. "props": {
  19. "type": "primary",
  20. "style": {
  21. "marginLeft": 10
  22. },
  23. "onClick": {
  24. "type": "JSExpression",
  25. "value": "function onClick(e) { this.utils.xxx(this.constants.yyy);}"
  26. }
  27. },
  28. "children": "click me"
  29. }]
  30. }]
  31. }
  1. import ReactRenderer from '@alilc/lowcode-react-renderer';
  2. import ReactDOM from 'react-dom';
  3. import { Button } from '@alifd/next';
  4. import schema from './schema'
  5. const components = {
  6. Button,
  7. };
  8. ReactDOM.render((
  9. <ReactRenderer
  10. schema={schema}
  11. components={components}
  12. appHelper={{
  13. utils: {
  14. xxx: () => {}
  15. }
  16. }}
  17. />
  18. ), document.getElementById('root'));

designMode

在生产环境下不需要设置。

designMode 属性主要在搭建场景中使用,主要有以下作用:

  • designMode 改变时,触发当前 schema 中所有组件重新渲染
  • designMode 设置为 extendborder 时,渲染模块会为 DialogOverlay 等初始状态无 dom 渲染的组件外层包裹一层 div,使其在画布中能够展示边框供用户选中
  • designMode 有值时,容器组件每次 render 都会更新自定义方法的绑定

suspended

渲染模块是否挂起,当设置为 true 时,渲染模块最外层容器的 shouldComponentUpdate 将始终返回false,在下钻编辑或者多引擎渲染的场景会用到该参数。

onCompGetRef

组件 ref 的回调,在搭建场景下编排模块可以根据该回调获取组件实例并实现生命周期注入或者组件 DOM 操作等功能,回调函数主要包含两个参数:

  • schema: 当前组件的 schema 模型结构
  • ref:当前组件的 ref 实例

onCompGetCtx

组件 ctx 更新的回调,在组件每次 render 渲染周期我们都会为组件构造新的上下文环境,因此该回调函数会在组件每次 render 过程中触发,主要包含两个参数:

  • schema:当前组件的 schema 模型结构
  • ctx:当前组件的上下文信息,主要包含以下内容:

  • page:当前页面容器实例

  • this: 当前组件所属的容器组件实例
  • item/index: 循环上下文(属性 key 可以根据 loopArgs 进行定制)
  • form: 表单上下文

rendererName

渲染类型,标识当前模块是以什么类型进行渲染的

  • LowCodeRenderer: 低代码组件
  • PageRenderer: 页面

customCreateElement

自定义创建 element 的钩子,用于在渲染前后对组件进行一些处理,包括但不限于增加 props、删除部分 props。主要包含三个参数:

  • Component:要渲染的组件
  • props:要渲染的组件的 props
  • children:要渲染的组件的子元素