阿里低代码框架 lowcode-engine 低代码表单实战(阿里低代码平台)

前沿

lowcode-engine功能比较强大,最近这段时间做了个低代码表单的实战,在过程中遇到一些问题,在这里做下介绍和总结。

功能演示

阿里低代码框架 lowcode-engine 低代码表单实战(阿里低代码平台)

前台功能

主要介绍一下前台功能的基本实现和一些问题。

FormContainer容器组件

我们的默认容器不是页面,而是需要自定义容器。例如,在常见的低代码平台中默认容器是表单容器,通过表单容器类提供布局能力。这块之前有一篇文章详情介绍,可以查看FormContainer容器。

那篇文章介绍了怎么实现自定义容器,我们打开详情页面,看到所有的表单项都是只读的,我们在容器中做一个全局状态管理,在这里用context去实现。

  • 定义 Provider

// 定义FormContainerProviderexport const FormContainerProvider: FC<IFormContainerProviderProps> = ({ children, isMobile }) => { const processorAction = useCreation(() => { return createFormContainerProcessor(); }, []); const { processor, getRoot, destroy } = processorAction || {}; useEffect(() => { processor.setMobile(isMobile); }, [isMobile]); useEffect(() => { return () => { destroy?.(); }; }, []); return <Context.Provider value={processor!}>{children}</Context.Provider>;};

  • 之后我们就可以在容器组件和FormItem组件内获取数据,这块简单做了封装处理。

// 从conext获取更改只读的方法const [changeReadonly] = useFormContainerSelector((s) => [s.changeReadonly]);

  • Form容器对外提供能力

我们提交保存操作没有在容器内实现对应的物料,是在外部自定义的,这时候就需要我们对FormContainer绑定Ref,之后我们获取实例可以拿到对应的方法。

// 绑定refReact.useImperativeHandle( ref, () => { return { formRef: form, changeReadonly, // 更改只读方法 }; }, []);

物料组件

我们对每个表单项开发对应的物料,物料的开发,官方提供脚手架快速创建项目,之前也写过一遍文章,流程不清楚的请移步自定义物料篇。这里我们用日期物料做说明,还会介绍一下开发调试,之前文章说我们要把物料发布到npm上,这样开发调试很不方便。

Filed Date 物料

  • 定义Date物料类型

可以看到我们有个基础的类型,是一些通用的属性,columnConfig这个属性是每个FormItem的config。

export interface IColumnEntity<T extends EFieldType = EFieldType> extends IBaseEntity { ... // 数据库字段类型 fieldType: TFieldType; // 标题 title?: string; // 扩展参数 extraParam?: Record<string, any>; // 列配置信息 columnConfig: T extends keyof TColumnConfigMap ? TColumnConfigMap[T] : TColumnConfig; // 校验信息 validateConfig: IColumnValidateConfig;}

  • FieldData config

日期物料的config信息,有了具体的TS类型,在我们写代码的时候会事半功倍

/** * 日期 */export interface IColumnDateConfig { /** * 描述 */ description: string; /** * 占位符 */ placeholder?: string; /** * 1. 普通 2禁用 3 只读 */ status: number; /** * 格式化类型 1. YY-MM 2. YYYY-MM-DD 3. YYYY-MM-DD HH:MM 4. YYYY-MM-DD HH:MM:SS */ format: number; /** * 默认值类型 */ defaultValueType: string; /** * 默认值 */ defaultValue: string;}

  • meta.ts信息

这里主要描述物料组件信息, 我们简单介绍一下setter信息,其它的可以看官方文档。

configure: { props: [ { title: { label: '格式', }, name: 'columnConfig.format', supportVariable: false, setter: { componentName: SelectSetter, props: { options: DateFormatConstant, changeReRenderEvent: true, }, initialValue: 2, }, }, ]}

props中的name属性columnConfig.format,我们可以使用这种方式来描述嵌套的属性。

  • 实现FieldData组件

这里相对来说也不复杂,需要注意的是porps中的内容,有我们在meta文件中定义的props,还有FormItem中标注的value,onChange属性,还有一些属性,大家可以打印下看看。有时候有些需求实现这上面的属性会有帮助,

// FieldData 具体实现export interface IFieldDateProps extends BaseWrapperProps<EFieldType.DATE> {}export const FieldDate: FC<IFieldDateProps> = (props) => { const { columnConfig, onChange, value, ...otherProps } = props; const [readonly] = useFormContainerSelector((s) => [s.readonly]); const format = columnConfig?.format; const currFormat = DateFormatConstant.find((f) => f.value == format); const onDateChange: DatePickerProps['onChange'] = (date, dateString) => { const currUnix = date?.valueOf(); onChange?.(currUnix); }; return ( <BaseWrapper {...props}> <DatePicker style={{ width: '100%' }} disabled={readonly || columnConfig?.status === EFieldStatus.disable} placeholder={columnConfig?.placeholder} showTime={currFormat?.showTime} format={currFormat?.label || 'YYYY-MM-DD'} value={value ? dayjs(value) : undefined} onChange={onDateChange} /> </BaseWrapper> );};

setter

实现我们的需求,setter是一个比较重要的环节,这里我们对setter做了重写,全部使用了antd的组件。setter我们分为通用的setter和单个物料的自己的setter。

  • setter定义

官方的案例Setter使用的是字符串,也就是在引擎注入的setter供我们使用。在项目中开发,我们可以用一个setter组件,待setter稳定后,考虑引擎注入。

  • 每个setter对应一个props属性

上面我们在meta文件中的columnConfig.format使用了SelectSetter,定义如下:

export const SelectSetterFun: FC<ISelectSetterProps> = (props) => { const { options = [{ label: '-', value: '' }], onChange, mode, value, showSearch, onChangeEvent, changeReRenderEvent, } = props; const dataSource = formateOptions(options); const { sendReRenderEvent } = useReRenderEvent({ isBindEvent: false }); return ( <Select style={{ width: '100%' }} value={value} size={'small'} options={dataSource} onChange={(val) => { onChange?.(val); onChangeEvent?.(val); changeReRenderEvent && sendReRenderEvent(); }} showSearch={showSearch} /> );};export const SelectSetter = SetterHoc(SelectSetterFun);

  • 高阶组件 SetterHoc 在setter中直接使用hooks组件会有问题,我们用类组件做一层包裹。

export const SetterHoc = (Component: any) => { return class SetterComponent extends React.Component { render() { return <Component {...this.props} />; } };};

  • 获取和设置其它props值

有的需求我们在setter中需要获取其它组件的属性,通过props?.field?.parent 可以获取到,这里封装了一个自定的hooks,来获取和设置值

export const usePropsValue = (props: any) => { const getPropValue = useMemoizedFn((key: string) => { const propsField = props?.field?.parent; // 获取同级其他属性 showJump 的值 return propsField.getPropValue(key); }); const setPropsValue = useMemoizedFn((key: string, value: any) => { const propsField = props?.field?.parent; // 获取同级其他属性 showJump 的值 propsField.setPropValue(key, value); }); return { getPropValue, setPropsValue, };};

还有一种方法可以可以实现此效果,就是在setter上设置extraProps属性,这个属性可以有两个方法setValue和getValue.

  1. 在meta上设置

// 更改其它选项,在meta上设置extraProps: OptionsSetterExtraProps,

// 更改其它选项,在meta上设置extraProps: OptionsSetterExtraProps,

  • setter之间通信

在引擎中,通信需要通过事件的方式去做。在这里,通常我们有些setter的变更会影响其它setter,例如:日期的格式变化默认值会做相应的调整。在业务中,setter的变更,通知依赖的setter刷新,刷新的时候重新获取属性值,做业务调整。

在这里,封装了reRender一个hooks,

export const useReRenderEvent = (props?: IUseReRenderEventProps) => { const { isBindEvent = true } = props || {}; const update = useUpdate(); // 强制触发更新 const reRenderEvent = useMemoizedFn(() => { update(); }); /** * 发送重新渲染事件 */ const sendReRenderEvent = useMemoizedFn(() => { event.emit(EFiledEventName.ReRenderEmit); }); useEffect(() => { isBindEvent && event.on(EFiledEventName.ReRender, reRenderEvent); return () => { isBindEvent && event.off(EFiledEventName.ReRender, reRenderEvent); }; }, [isBindEvent]); return { sendReRenderEvent, };};

这个hooks,有两个作用,一个是发送重新渲染事件,一个是监听渲染事件。在上面的案例当中,

1.在格式的setter中引入该hooks,做事件发送。

const { sendReRenderEvent } = useReRenderEvent({ isBindEvent: false });return ( <Select ... onChange={(val) => { changeReRenderEvent && sendReRenderEvent(); }} ... />);

  1. 在默认值setter中,做事件的监听。

// 监听格式的变化useReRenderEvent();// 获取格式数据const { getPropValue } = usePropsValue(otherProps);const format = getPropValue('format');

渲染详情页

封装FormContainerRnder组件,来做渲染。

  • 引擎提供了ReactRender的能力,我们传入对应的scheam信息,就可以做到显示。

<ReactRenderer className="lowcode-plugin-sample-preview-content" schema={schema} designMode="dialog" rendererName="LowCodeRenderer" components={components} onCompGetRef={onCompGetRef} appHelper={{ requestHandlersMap: { Fetch: createFetchHandler(), }, }}/>

  • 获取FormContainer组件Ref

在数据提交的时候,我们需要获取组件的实力,在引擎中获取Ref方法,要使用 onCompGetRef方法。

const onCompGetRef = (schema: any, ref: any) => { if ('FormContainer' === schema.componentName) { const { formRef, ...otherRef } = ref; formInstanceRef.current = ref.formRef; formOtherRef.current = otherRef; // 获取到ref,执行resolve promiseRef?.resolve(true); }};

在渲染的时候,我们有可能获取不到实例,我们用个异步来处理。

// 此处异步是因为不能立马获取到form的实例const promiseRef = useCreation(() => { return createPromiseWrapper();}, []);

提供对外的数据能力

React.useImperativeHandle( ref, () => { return { getFormInstance: async () => { await promiseRef.promise; return formInstanceRef.current! as FormInstance; }, changeReadonly: async (disabled: boolean) => { await promiseRef.promise; formOtherRef.current?.changeReadonly?.(disabled); }, }; }, []);

  • 初始化数据

打开编辑详情页的时候,需要把从接口获取的数据给设置到表单上。有了FormContainer实例,我们可以很方便的做设置

useAsyncEffect(async () => { if (mode !== EMode.create && !itemData.loading && Object.keys(itemData.data).length > 0) { // 获取实例 const formInstance = await formRef.current?.getFormInstance(); // 数据转换 const formValues = convertItemDataToFormValues(itemData.data, table.data.columns); // 设置值 formInstance?.setFieldsValue?.(formValues); }}, [itemData.data, itemData.loading]);

提交数据

获取表单数据,做提交。这里通过FormContainer的时候,可以获取所有的值,包括做一些前端的校验等。

  • 获取所有值,调用api,做数据提交

export const getFormValues = async (formRef: React.MutableRefObject<IPreviewRef>) => { const formInstance = await formRef?.current?.getFormInstance(); return formInstance?.getFieldsValue();};

开发调试

开发物料后,如果我们发布npm,整个流程会很繁琐,效率低,物料脚手架也提供了调试,不过在我们实际业务开发中,会有一些业务数据和上下文的环节依赖,所有要能实时调试开发。接下来几个步骤介绍一下

  • 启动lowcode开发模式

"lowcode:dev": "build-scripts start --config ./build.lowcode.js",

会开启一个实时的监听服务。

  • 在我们引擎中的assets.json修改,使用上面服务的地址,修改内容如下

阿里低代码框架 lowcode-engine 低代码表单实战(阿里低代码平台)

修改在url中的内容为本地地址,这时候我们开发后。刷新浏览器,会实时看到结果

  • 环境变量,动态切换

import assetsLocal from '../services/assets-local.json';import assets from '../services/assets.json';export const getAssetsJson = () => { // 用本地配置文件 if (process.env.LOCAL_UI_MATERIAL === 'true') { return assetsLocal; } return assets;};

总结

以上就是对lowcode-engine低代码实战内容,后续我们介绍一下引擎和后台之间的交互,可以让大家实现一个完整的案例。

作者:Witty_Wizard
链接:https://juejin.cn/post/7346865556328808463

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2024年7月8日 上午11:39
下一篇 2024年7月8日 上午11:50

相关推荐

  • 许昌农商银行:惠民利民办实事 党建金融建新功(农商行党建+金融)

    本网讯(梁靖 徐钲顺 岳永歌)近日,许昌农商银行多措并举,以实际行动落实省联社党委各项安排部署,将党建工作与业务经营深度融合,践行主题教育“学思想、强党性、重实践、建新功”的总要求…

    科研百科 2023年7月14日
    328
  • 科研废物导航网

    科研废物导航网 科研废物导航网是一个致力于帮助研究人员识别,处理和处置科研废物的在线平台。科研废物是指在实验室中产生并无法回收利用的废物,例如废弃物,样品,实验材料等。这些废物通常…

    科研百科 2024年10月31日
    239
  • 国防科研项目增值税税率

    国防科研项目增值税税率 随着国防科研项目的不断进步和发展,增值税税率也在不断变化。作为国家税收制度的重要组成部分,增值税税率的调节对于维护国家经济稳定和促进社会发展具有重要作用。 …

    科研百科 2025年1月31日
    0
  • 科研项目管理系统课设

    科研项目管理系统课 科研项目管理系统课 随着科技的不断进步,科研项目管理系统已经成为项目管理中不可或缺的一部分。但是,传统的科研项目管理系统存在着一些缺陷,例如无法很好地支持团队协…

    科研百科 2025年1月21日
    0
  • 考试项目管理考试内容(考试项目管理考试)

    考试项目管理考试考试项目管理考试一般是按照知识+考点为主的,它是一个综合性的考试,由高考考生将考试科目、学科成绩、高考项目、分数等综合性的科目所组成。在考试中,它有不同的层次,包括…

    科研百科 2024年9月28日
    17
  • 行政事业单位经费管理办法

    行政事业单位经费管理办法 为规范行政事业单位经费管理,提高经费使用效率,根据《中华人民共和国预算法》等相关法律法规,我部制定了行政事业单位经费管理办法。现将办法印发给你们,请严格执…

    科研百科 2024年11月30日
    0
  • 哪个协同办公软件好

    协同办公软件是组织中使用的计算机软件,用于协作和共享文件、信息和资源。选择一个合适的协同办公软件可以帮助员工更高效地工作,提高协作效率。在本文中,我将介绍一些常用的协同办公软件,并…

    科研百科 2024年8月26日
    32
  • 公司科研项目管理考核办法

    公司科研项目管理考核办法 为了加强公司科研项目的管理,提高科研项目的质量和效率,公司制定了科研项目管理考核办法。该办法旨在对公司科研项目管理人员进行考核和评价,激励他们不断提高管理…

    科研百科 2024年4月8日
    196
  • 以高度政治自觉抓实党员教育管理(以高度政治自觉抓实党员教育管理工作)

    搞好军队党的建设,是军队建设发展的核心问题,是军队全部工作的关键,关系到党的执政地位,关系到我军性质宗旨,关系到部队战斗力。党员教育管理是军队党的建设基础性工程和重要内容,必须以高…

    科研百科 2023年1月16日
    399
  • 积极创新党建工作 加强党务规范化建设

    党支部是党的基础组织,是党组织开展工作的基本单元,是党在社会基层组织中的战斗堡垒,是党的全部工作和战斗力的基础。菏泽鲁西新区岳程街道扎实推进农村党支部党务规范化建设,按照活动场所规…

    科研百科 2023年9月19日
    164