低代码画布渲染之显示组件

您所在的位置:网站首页 低代码设计 低代码画布渲染之显示组件

低代码画布渲染之显示组件

2023-02-20 05:30| 来源: 网络整理| 查看: 265

低代码画布渲染之显示组件

低代码引擎是低代码分层架构中最复杂的部分,引擎的核心功能包含入料、设计、画布渲染和出码等,它们的含义如下:

入料:向引擎注入设置器、插件和组件。 设计:对组件进行布局设置、属性设置以及增删改操作后,形成符合页面搭建协议的JSON Schema。 画布渲染:将 JSON Schema 渲染成 UI 界面。 出码:将 JSON Schema 转化成手写代码,这通常发生在页面发布的时候。

在之前的文章中介绍了低代码跨 iframe 拖拽,本文开始介绍画布渲染。画布渲染就是将设计器生成的 JSON Schema 渲染成 UI 界面,画布渲染有一个单独的 npm 包,简称 ReactRenderer,它与设计器不直接联系,而是通过 SimulatorRenderer 与设计器联系,SimulatorRenderer是另一个 npm 包。画布渲染至少包含四部分内容:

显示组件:这是画布渲染最基础的部分,不涉及任何交互,只是简单的显示。 获取数据源:让组件获取它要显示的数据。 表单联动:使表单控件的状态受其他数据的控制,包含禁用联动、显隐联动和取值联动。 表单校验:校验表单填写的值是否符合要求,不符合则给出错误提示。

本文只介绍画布渲染中的显示组件。

ReactRenderer 的作用是将 JSON Schema 描述的组件树显示在界面上,总体而言,它是一个 React 组件,接受如下属性:

interface Props { // 页面的 json schema schema: PageSchema; // schema 中使用的组件 components: Map; // schema 中的组件装载到界面后要执行的勾子 onCompGetRef?: (schema: NodeSchema, domElement: HTMLElement | null) => void; // 画布渲染模式,设计态或运行态,默认值为运行态 rendererMode?: RendererMode; // 容器组件没有子元素时的提示语 customEmptyElement?: (schema: NodeSchema) => React.ReactNode; } 复制代码

上述 schema 和 components 是必填属性,schema 中用到组件必须在 components 中声明,否则画布无法正常渲染。onCompGetRef 是选填属性,在设计态时它为设计器获取 Node 的位置提供了可能。

假如有如下一段 JSON Schema。

{ "componentName": "Page", "packageName": "Page", "containerType": "Page", "isContainer": true, "id": "def133", "children": [ // 行 { "componentName": "Row", "packageName": "vitis-lowcode-row", "containerType": "Layout", "isContainer": true, "id": "def134", "props": [], "children": [ // 列 { "componentName": "Column", "packageName": "vitis-lowcode-column", "props": {}, "isContainer": true, "id": "def135", "containerType": "Layout", "children": [ { "componentName": "Select", "packageName": "vitis-lowcode-select", "props": {"label": "性别"}, "extraProps": {"name": "sex"}, "isFormControl": true, "id": "def136", } ] }, // 列 { "componentName": "Column", "packageName": "vitis-lowcode-column", "props": {}, "isContainer": true, "containerType": "Layout", "children": [] "id": "def137", } ] } ], "props": { "style": "padding: 10px" }, "extraProps": { // 这是数据源字段,该字段在下一个小节介绍 "dataSource": {...} } } 复制代码

上述 schema 在界面上将显示为一行两列布局,第一列有一个下拉选择器,如下图:

loyout.png

ReactRenderer 将 schema 描述的组件分为4种类型,如下:

页面容器:这是 schema 的 root 必须是页面容器,它没有发布成单独的 npm 包,而是存在于 ReactRenderer 的内部。 布局容器:它通常是页面容器的 children,用来控制页面的布局,比如:行和列。 表单控件:它处于 schema 嵌套层级的最后一层,通常位于布局容器中,既能展示数据又能接受用户输入。 普通UI组件:它处于 schema 嵌套层级的最后一层,通常位于布局容器中,只能显示数据不能接受用户输入。 页面容器

页面容器是整个画布的根节点,对应的 React 组件是 PageRenderer,与视图相关的代码如下:

function PageRenderer(props: Props) { const context = useContext(Context) const rootRef = useGetDOM(props.schema) // line A const { style } = props.schema.props return ( { !props.schema.children.length ? context.customEmptyElement ? context.customEmptyElement(props.schema): null: {props.schema.children.map(child => )} } ) } 复制代码

如果页面容器有 children,那么 PageRenderer 将遍历每一个 child,将其显示在界面,没有 children,则显示提示语。BaseComponentRenderer 是一个 React 组件工厂,它根据 schema 描述的组件类型,分门别类的渲染组件。

PageRenderer 中最重要的代码是 line A 用到的 useGetDOM,它是一个 React Hook,其作用是等组件装载之后将组件的根 DOM 元素传递出去,让设计器能完成拖拽定位。useGetDOM 的代码如下:

function useGetDOM(schema: NodeSchema) { const context = useContext(Context) const rootRef = useRef(null) useEffect(() => { if (context.rendererMode === RendererMode.design && context.onCompGetRef) { context.onCompGetRef(schema, rootRef.current) } return () => { if (context.rendererMode === RendererMode.design && context.onCompGetRef) { context.onCompGetRef(schema, null) } } },[]) return rootRef } 复制代码 布局容器

行组件和列组件都属于布局容器,但列组件必须放置在行组件的 children 中,布局容器与视图相关的代码如下:

function LayoutComponent(props: Props) { const rootRef = useGetDOM(props.schema) const context = useContext(Context) const { style, ...reset } = props.schema.props const Component = context.components.get(props.schema.componentName) // lineA if (!Component) { return 未知的布局组件} return ( {!props.schema.children.length ? context.customEmptyElement ? context.customEmptyElement(props.schema): null : props.schema.children.map(child => ) } ) } 复制代码

布局容器究竟要渲染哪一个组件,这取决于 lineA 的取值,取值结果直接决定了界面上要显示的内容。

表单控件

表单控件能接受用户输入,存储用户输入的值,以及表单联动将在后续的小节重点介绍。表单控件与视图相关的代码如下:

function FormControl(props: Props) { const rootRef = useGetDOM(props.schema) const context = useContext(Context) // 获取要渲染组件 const Com = context.components.get(props.schema.componentName) if (!Com) { return 未知的表单控件 } return ( ) } 复制代码 普通UI组件

普通 UI 组件只能用来展示数据,它的代码如下:

function UIComponent(props: Props) { const rootRef = useGetDOM(props.schema) const context = useContext(Context) const Com = context.components.get(props.schema.componentName) if (!Com) { return 未知的组件 } return ( ) } 复制代码 小节

画布渲染的第一步就是要组件显示在界面上,不涉及任何交互,获取数据源、表单联动和表单校验是下一步要做的,在后续文章将单独介绍。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3