两年前我设计了H5-Dooring的第一个开源版本, 之后陆陆续续迭代了两年, github star已达到6.5k+, 也找到了很多志同道合的小伙伴, 一起研发Dooring系的搭建产品, 如:
从技术设计和产品规划上, 这几年也总结摸索出了一些经验和实践, 接下来我就和大家一起分享一下H5-Dooring 的技术架构设计与演进。
我们都知道任何低代码或者零代码搭建产品都非常注重底层搭建协议, 这些产品通常会设计一套向上兼容且可扩展的DSL结构, 来实现页面元件的标准化配置, 并支持元件的向上扩展。
上面这张图是我在设计 V6.Dooring 可视化大屏搭建平台的编辑器架构图, 这里的底层搭建协议可以认为是 搭建基础, 也就是我们常说的 “经济基础决定上层建筑”。
在设计H5-Dooring 搭建平台前, 我也参考了很多标准化软件数据协议, 给我启发最大的就是 ODATA, 它是微软于2007年发起的开放协议, 主要由以下几部分组成:
「核心协议」: 主要定义了开放数据协议的核心语义和行为。
为了让可视化搭建平台的组件数据标准化且可扩展, 这里我分享一下H5-Dooring的Schema设计。
Schema 分两部分:
editData 是 组件属性可编辑项的数组, 每一项里面包含了如下字段:
key和name 都可以按照组件属性的语义来定, 这里值得一提的是 type. 不同属性的值类型不同, 所以我们编辑项的 type 也不同, 所有的类型如下:
config 本质上是一个对象, 也就是组件所能暴露出来的属性集合, 和 editData 数组每一项的key 一致, 如下:
{
cpName: 'Header',
logoText: '',
fontSize: 20,
color: 'rgba(47,84,235,1)',
height: 60,
fixTop: false,
menuList: [
{
id: '1',
title: '首页',
link: '/'
},
{
id: '2',
title: '产品介绍',
link: '/'
},
]
}
我们通过以上的设计规范, 就可以轻松制作一个可实时编辑的低代码组件:
可以在Dooring官方文档体验: 低代码组件案例。
最开始设计H5-Dooring的时候为了最大限度的降低用户的搭建成本, 我采用了智能网格布局的方式来搭建页面, 用户只需要在二维空间像搭积木一样选择适合的组件就可以快速的制作页面:
这样虽然可以降低用户的搭建难度, 并能满足一部分受众的搭建需求, 比如说简单的官网, 活动页面制作,下面是一个搭建的比较有代表性的例子:
但是对于平台方, 为了满足更多场景的页面深度制作, 就必须提供不同场景不同行业的组件物料, 这将对研发带来巨大的压力(虽然也一直在添加新组件)。
另一方面, 目前上很多H5活动制作平台基本上都采用的自由布局的模式搭建, 好处就是可以最大限度的还原设计稿, 满足更灵活的搭建需求, 缺点就是使用成本比网格布局的模式要高, 还会涉及图层的概念。
当然综合评估下来, 确实很有必要给一部分用户提供自由布局的模式, 所以在技术层我设计同时兼容网格布局和自由布局的搭建方案. 当用户在搭建时, 可以轻松选择自己适合的搭建模式:
同时为了满足自由布局下组件的层级管理, 我又设计了图层管理面板和图层操作, 来快速的管理页面元素, 当然图层管理面板 对网格布局 也同样有一定积极作用, 比如快捷的操作组件。
在前面提到了可视化搭建平台的统一搭建协议和搭建模式, 在这两个核心要素完成之后, 我们就很容易的去设计我们的插件系统。
从插件系统的本质来看, 核心价值是对页面操作的整个周期里为页面赋能, 而页面的本质是数据(也就是DSL集)。
所以只要有标准的数据规范, 我们自定义的插件就可以很轻松的来对页面进行赋能, 类似于各种技术里面的中间件. 下面是一个例子:
{
"pageConfig": {
"allowOverlap": "freedom",
"isLogin": false,
"bgColor": "rgba(16,20,29,1)",
"bgSize": "100%",
"title": "H5-Dooring官网"
},
"tpl": [
{
"id": "276059",
"item": {
"category": "base",
"config": {
"cpName": "XButton",
"id": "",
"bgColor": "rgba(22,40,212,1)",
"width": 190,
"marginTop": 0,
"round": 16,
"text": "按钮",
"fontSize": 15,
"color": "rgba(255,255,255,1)",
"animation": "none",
"animationTurn": 1,
"delay": 0,
"interaction": {
"type": "link",
"title": "",
"params": "",
"content": "",
"height": 300,
"width": 300,
"okText": "",
"cancelText": "",
"onOk": "",
"btnColor": "rgba(20,54,226,100)"
}
},
"h": 23,
"type": "XButton"
},
"point": {
"w": 24,
"h": 23,
"x": 0,
"y": 0,
"i": "276059",
"moved": false,
"static": false,
"isBounded": true
},
"status": "inToCanvas"
},
{
"id": "260487",
"item": {
"category": "base",
"config": {
"cpName": "LongText",
"id": "",
"text": "我是长文本有一段故事,dooring可视化编辑器无限可能,赶快来体验吧,骚年们,奥利给~",
"color": "rgba(60,60,60,1)",
"fontSize": 14,
"indent": 0,
"lineHeight": 1.8,
"textAlign": "left",
"bgColor": "rgba(255,255,255,0)",
"padding": 0,
"radius": 0
},
"h": 36,
"type": "LongText"
},
"point": {
"w": 24,
"h": 36,
"x": 0,
"y": 23,
"i": "260487",
"moved": false,
"static": false,
"isBounded": true
},
"status": "inToCanvas"
}
]
}
上面是H5-Dooring生成的一个页面DSL结构, 如果我们要对页面元素进行统计分析, 或者实现出码, 国际化, PSD解析转化等功能, 只需要对数据结构进行分析和处理即可。
所以说在H5-Dooring平台实现自定义的插件还是非常容易的, 也是低代码或者无代码需要重点规划的一个环节。
H5-Dooring平台的组件编辑器主要是对组件属性进行编辑,比如:
当然还有全局的数据源配置. 如下:
同时由于我们的组件数据协议高度统一, 所以如果想扩展属性配置, 也非常容易, 我们只需要按照数据协议添加属性即可:
同理, 「v6.dooring」 也采用相似的架构, 所以我们可以轻松扩展组件的属性:
有关可视化大屏搭建平台的技术实践可以参考我的另一篇文章 从零设计可视化大屏搭建引擎。
由于Dooring的技术栈采用React, 并实现了标准的数据协议层, 所以我们可以利用类似 Taro 等跨平台框架实现多端搭建, 对于我们常用的媒介如移动端, Pad和PC端, 目前编辑器也提供了快捷的切换模式:
所以我们可以轻松的实现不同端的搭建, 实现原理本质上是通过切换画布大小, 并同比例更新元素的计量衡。
图层管理模块也是在Dooring支持了自由布局之后才上线的功能. 因为我们页面中组件的数据结构中包含统一的物理信息:
所以我们只需要分析页面的组件集合, 就可以轻松的渲染出页面中的元素图层信息:
有了图层的概念我们其实可以做很多有用的事情, 比如:
后面 Dooring 也会基于图层能力迭代更多提高用户搭建销效率的功能。
在Dooring 的迭代中花了大部分精力在优化用户搭建体验和协议标准化上, 对于组件物料的丰富上, 我也做了一些设计, 最近也发布了一套低代码组件库的原型:
我们可以轻松的像写 React 组件一样来实现低代码组件, 并支持线上实时编辑, 一个基本的例子如下:
import styles from './index.less';
import React, { memo, useState } from 'react';
import { MenuOutlined } from '@ant-design/icons';
import { IHeaderConfig } from './schema';
const Header = memo((props: IHeaderConfig) => {
const {
cpName,
bgColor,
logo,
logoText,
fontSize,
color,
showMenuBtn,
menuColor,
height,
} = props;
const [showMenu, setShowMenu] = useState(false);
const toggleMenu = () => {
setShowMenu(!showMenu);
};
return (
className={styles.header}
style={{ backgroundColor: bgColor, height: height + 'px' }}
>
{logoText}
{showMenuBtn && (
<>
className={styles.menuIconWrap}
onClick={toggleMenu}
style={{ color: menuColor, borderColor: menuColor }}
>
>
)}
);
});
export default Header;
通过这种标准化的方式, 我们可以给 Dooring 平台提供更为丰富的组件物料。
除了基础物料组件之外, 为了从更大粒度提高用户搭建的效率, 我提供了模版功能, 我们可以把重复的区块和可复用的页面保存为模版:
我们可以在编辑器页面轻松将页面保存为模版, 并自动生成海报封面:
基于网页生成封面的方式也很简单, 我这里采用的是 dom-to-image 这个库, 当然搭建也可以使用html2canvas。
表单编辑器的实现思路我之前也写过一些分享, 这里和大家再介绍一下核心的一些思路。
「1. 静态化配置列表」
静态化配置列表是最传统的表单配置方式之一,基本思路就是利用母表来生成配置项,进而实现表单配置。类似于以下方式:
早期的网站配置就是类似于这种呢方案实现的,比如说我们要定制网站的主色,网站某些组件是否可见,是一种比较简单的方式。但是缺点是每增加一个配置属性,都要开发人员重新编写一个字段配置代码,这种方式在表单开发中非常不灵活,而且对代码层有强依赖性,所以只适合做小型配置系统。比如个人网站,简单的自定义表单。
「2. 基于json schema的动态表单配置」
基于「json schema」的动态表单配置有两种实现方案, 一种就是支持在线修改json文件从而实现定制化,另一种就是完全无代码操作,但是前提都需要提供一套通用的表单模版。类似于如下案例:
此种方案可以实现基本的表单自治。也是本文主要实现的方案。至于在线编写json文件的方案。笔者之前也也过成熟的方案,具体可以参考:基于jsoneditor二次封装一个可实时预览的json编辑器组件(react版)。
「3. 支持在线coding的混合式表单设计」
支持「在线编程」的混合式表单设计方案是终极方案,也是目前流行的无代码化平台的思想之一。一方面它提供了基于「json schema」的动态表单配置, 对于一些强定制的,需要在线设计组件方案的模式,采用在线编程,实时打包成动态组件的方式,最后根据平台的组件约定来实现组件库的方式。如下图所示:
在线代码编辑可以使用「react-codemirror2」或者 「react-monaco-editor」插件来实现。至于在线打包,我们用「nodejs」完全可以实现,笔者在做「Dooring」项目的在线下载代码时就用到了该方案,感兴趣的可以了解一下。
可视化领域一方面强调的是图形(可视化)的设计,一方面是动态表单。比如说我们想傻瓜式的改变一张图的数据,属性,交互等,我们需要通过表单这一桥梁来实现:
所以我们需要设计一款适合公司产品的“表单引擎”,来动态根据图形组件的类型渲染不同表单配置。这块思想也是表单设计器要解决的问题之一。在下面的文章中我们会详细介绍实现过程。
在实现表单设计器之前,我们先来整理一下思路和需求。在笔者的最初草图中,它长这样:
从草图中我们可以提取到如下任务信息:
我们这里总结了几个常用的表单组件如下:
以上这些基本满足我们的日常开发需求,其次我们还可以开发数据源表单组件,列表组件,比如dooring实现的那样:
类似的还有颜色面板这些,我们可以更具业务需求自行定制。
在完成表单组件库之后,我们就需要根据配置项动态渲染了。也有两种实现思路,一种就是类似于多条件判断,如下:
{
item.type === 'Number' &&
这样做虽然可行,也有很多成熟系统采用该方案,但是一旦表单变多,比如一个页面有几十个甚至上百个表单项,那么我们将渲染「m」 *** n**次(m为表单组件类型数,n为配置项个数)。另一种方式笔者看来是比较优雅的,可以将复杂度降低到O(n),也就是笔者常用的对象法。思路大至如下:「将表单组件的类型作为对象的属性,属性值为对应的表单组件,这样遍历的时候只需要对应上对象的具体类型即可。」 代码如下:
// 维护表单控件, 提高form渲染性能
const BaseForm = {
"Text": (props) => {
const { label, placeholder, onChange } = props
return |
},
"Number": (props) => {
const { label, placeholder, onChange } = props
return |
}
}
// 动态渲染表单
{
formData.map((item, i) => {
let FormItem = BaseForm[item.type]
return
})
}
是不是很优雅呢?后期我们只需要在「BaseForm」里维护表单组件即可,而且还可以基于「BaseForm」对表单进行包装,实现动态删除,编辑等功能。如下:
包装后的代码如下:
接下来我们看看表单的全局属性,通过实际分析我们
文章标题:如何评价Dooring低代码/零代码搭建平台?
分享链接:http://www.shufengxianlan.com/qtweb/news48/479398.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联