hi, 大家好, 我是徐小夕. 今天和大家分享一下零代码搭建平台 Dooring 最新版 3.5 的 技术架构
, 产品设计思路
, 产品技术目标
(帮助个体和企业低成本的拥有适合自身业务的可视化搭建平台) 以及未来规划
.
Dooring 从 2020
年开源第一个版本至今已经过去 4
年了, 基于对 技术
和 用户体验
的极致追求, 每一年我们都做了大量的更新迭代, 期望能把用户的 搭建体验
做到最好, 覆盖更多的使用场景. 也很感谢和我一起做 Dooring
的小伙伴们, 能让Dooring系列搭建产品
在技术的潮流中不断沉淀和进化.
github star : 8.2k+
线上累计注册用户: 10000+
线上页面总数: 10000+
模版总数: 1000+
组件总数: 50+(持续生产中)
累计PV(浏览量): 500w+
累计UV(独立用户访问): 10w+
同时为了让技术小伙伴更好的研究学习低代码和零代码, 我在掘金和趣谈前端公众号
里也写了很多篇低代码的实现原理的文章, 后续也会随着产品不断迭代持续分享最新的技术实现.
这几年我对 Dooring
的定位一直没有变, 就是要做一款功能强大,高可扩展的零代码
解决方案,致力于提供一套简单高效
、专业可靠
、业务定制度高
的页面可视化搭建最佳实践。从2020年的孤军奋战到现在吸引了不少优秀的大佬加入开发和设计, 这里分享一下我们的迭代进程:
2020年, H5-Dooring编辑器1.0上线
纯前端编辑器版本
15+组件物料
网格布局搭建
nodejs
基础数据服务
2021年, H5-Dooring编辑器2.0上线
编辑器重构, 优化(支持DSL导入导出, 出码能力)
30+组件物料
网格布局搭建
模版库功能上线
基于 koa
二次封装的服务端
v6.Dooring可视化大屏编辑器上线
业务管理端闭环
2022年, Dooring2.5发布, Saas版上线
编辑器重构(搭建引擎优化,支持多模式搭建渲染)
40+组件物料
支持组件图层面板
智能网格布局 + 自由布局搭建
支持数据源配置
DooringSaas
零代码搭建平台上线
基于nest.js + mysql
的 saas
服务端
基于vite + vue3
的 Saas
管理后台
2023年, Dooring3.0发布, Saas2.0上线
编辑器重构升级
50+组件物料
出码能力增强(生成小程序, web, 支持h5打开小程序)
实现跨组件通信
数据源模式重构
添加设计辅助(文件导入, 参考线, 网格线, 画布快捷尺寸设置, 组件图层管理)
会员体系上线
上线java + mysql
的 springboot
服务端架构
全平台添加数据埋点 + 监控分析页面
从用户体验到核心技术架构, 我们一直在不断优化迭代, 2024
年 Dooring
会在业务场景
和AI & 协同能力
上做进一步升级和迭代.
我画了一张图以便大家更好的了解 Dooring
的技术方案.
接下来我们来聊聊最新版 Dooring
的功能和技术实现.
目前我们常见的低代码搭建模式都是 自然流布局
(拖拽完全遵循文档流移动), 比较符合实际开发的体验, 出码比较自然, 缺点就是拖拽体验比较差, 搭建成本偏高, 搭建自由度比较低, 所以低代码产品很难避免开发的介入, 对于跨界使用往往需要较高的培训使用成本.
而零代码主要面向非技术人群, 可以帮助非技术用户快速搭建出专业的网页应用. 目前常用的零代码搭建模式是 自由布局
, 也就是组件可以任意移动, 堆叠. 它的优点是上手成本很低, 搭建自由度比较高, 但是如果想适应多种屏幕尺寸, 开发成本就比较大了.
当然还有一种搭建模式, 也是 Dooring
早期使用的一种模式, 网格拖拽布局
. 我们可以使用二维网格移动来搭建页面的布局结构, 优点就是元素位置可以自动适应空间, 搭建成本很低, 对页面适配上也有一定改善, 缺点就是无法做自由度更高的元素堆叠等场景. 所以网格布局更适合做设计要求没那么高的业务页面.
随着业务场景和用户使用需求的升级, Dooring
在搭建上支持了双渲染搭建
模式, 即一套DSL可以支持网格布局
和 自由布局
两种搭建模式, 用户可以根据需求来切换搭建模式.
对于实现这两种布局方案, 市面上也有比较成熟的方案, 比如 react-dnd
, 或者 react-dragable
, 当然我们自己用 vue
或者 react
实现类似的搭建模式也完全没问题.
Schema 分两部分:
editData 组件可编辑属性的数组
config 组件真正消费的数据
editData
是 组件属性可编辑项的数组, 每一项里面包含了如下字段:
key 属性名
name: 属性名的中文显示
type: 属性的可编辑类型
isCrop(可选)
cropRate(可选)
range(type 为'Radio'或'Select'时的选项数组)
后期可能会扩展(详细结构可参考Dooring 开源版本)
key
和name
都可以按照组件属性的语义来定, 这里值得一提的是 type
. 不同属性的值类型不同, 所以我们编辑项的 type
也不同, 所有的类型如下:
Upload 上传组件
Text 文本框
RichText 富文本
TextArea 多行文本
Number 数字输入框
DataList 列表编辑器
FileList 文件列表编辑器
InteractionData 交互设置
Color 颜色面板
MutiText 多文本
Select 选择下拉框
Radio 单选框
Switch 开关切换
CardPicker 卡片面板
Table 表格编辑器
Pos 坐标编辑器
FormItems 表单设计器
更详细的代码可以参考私有化部署版的editor/src/core/FormComponents
目录.
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: '/'
},
]
}
editData
和 config
构成了一个 Dooring
组件的 schema
结构, 所以我们可以发现, 每一个 dooring
组件都具备如下结构:
index.tsx 组件主文件(可以集成任何第三方开源库)
index.less 组件的样式文件
schema.ts 组件的schema(组件描述协议)
editData
config
当然组件的 schema
也可以根据自己的需求来扩展, 如果在组件设计上有疑问的, 可以随时和我沟通.
组件物料开发依赖于上一节说的搭建协议的设计, 在开发 Dooring
自定义组件时我们只需要按照通用的 react
组件开发模式来写我们的组件即可, 唯一不同的就是每一个组件都需要定义自己的schema
文件, 这也是低代码/零代码组件开发的通用模式.
接下来我拿 Header
组件来和大家介绍一下如何开发自定义的低代码组件.
import styles from './index.less';
import React, { memo, useState } from 'react';
import { IHeaderConfig } from './schema';
const Header = memo((props: IHeaderConfig) => {
const { cpName, bgColor, logo, height } = props;
return (
你的自定义的header内容
);
});
export default Header;
.header {
box-sizing: content-box;
padding: 3px 12px;
background-color: #000;
.logo {
max-width: 160px;
overflow: hidden;
img {
height: 100%;
object-fit: contain;
}
}
}
const Header = {
editData: [
...baseConfig,
{
key: 'bgColor',
name: 背景色,
type: 'Color',
},
{
key: 'height',
name: 高,
type: 'Number',
},
{
key: 'logo',
name: 'logo',
type: 'Upload',
isCrop: false,
cropRate: 1000 / 618,
}
],
config: {
...baseDefault,
bgColor: 'rgba(245,245,245,1)',
logo: [
{
uid: '001',
name: 'image.png',
status: 'done',
url: 'http://cdn.dooring.cn/dr/logo.ff7fc6bb.png',
},
],
height: 50,
},
};
export default Header;
在开发完组件后, 我们需要把组件导入到对应的组件分类入口, 比如基础组件(BasicComponents),我们需要在BasicComponents/schema.ts
中导入并导出:
import Carousel from './Carousel/schema';
import Form from './Form/schema';
import Header from './Header/schema';
import WhiteTpl from './WhiteTpl/schema';
import Icon from './Icon/schema';
import Image from './Image/schema';
import Shape from './Shape/schema';
import LongText from './LongText/schema';
import Notice from './Notice/schema';
import Qrcode from './Qrcode/schema';
import Text from './Text/schema';
import Title from './Title/schema';
const basicSchema = {
Carousel,
Form,
Header,
Icon,
Image,
LongText,
Title,
// ...其他组件
};
export default basicSchema;
组件设计好之后在编辑器中还无法看到, 这是应该我们需要配置一下组件的初始化元信息, 比如从组件面板拖入画布之后的组件大小, 组件的名称等, 具体的定义路径在:
editor/src/components/BasicShop/template.ts
具体定义介绍:
{
base: [
{
type: 'Header', // 组件类型
h: 66, // 组件初始高度px
w: 375, // 组件宽度px
displayName: '页头组件', // 组件展示信息
icon: 'http://cdn.dooring.cn/dr/header.png', // 组件展示icon
category: 'base' // 组件的上层分类
}
],
}
目前表单搭建是集成在表单组件的配置项中的, 用户可以拖拽表单组件来轻松的创建表单, 并可配置表单的基本校验和自定义表单提交接口.
未来我们把把表单引擎单独抽离成一个子产品, 用来专门做表单搭建平台. 目前已经有一个 beta
版本:
后面我会单独写一篇文章来介绍这块的功能和技术设计.
出码模块主要有:
生成编译版本页面代码
生成小程序
生成页面 json schema 文件
原理就是通过渲染基座, 通过业务流将用户搭建的页面 schema
注入基座工程, 基座工程通过打包流将页面代码产出.
画布辅助设计主要是为了帮助用户更精准的进行页面搭建, 使得非技术人员也能做出专业的页面设计. 接下来分享一下 Dooring
在画布辅助上做的改进.
这块主要借鉴了老牌设计软件 PhotoShop
, 我们可以便捷的在 Dooring
的标尺双击来生成参考线(包括x
轴, y
轴), 我们可以把参考线拖拽到画布任意位置, 来实现对元素定位的参考.
标尺设计主要是为辅助参考线, 进行更精准的参考线位置和布局的规划, 随着画布的缩放, 参考线也会等比例缩放, 保证和画布一致.
网格线的价值在于用户可以在非设计稿的情况下, 精准控制元素的位置, 比如对齐, 排列等, 我们可以通过网格布局(Dooring的设计哲学之一) 的搭建模式下更快速的布局和排版页面.
在传统搭建平台里, 如果没有丰富的模版支持撑, 小白用户很难做出精致的页面, 包括设计元素, 包括色彩搭配等, 所以基于这样的背景, Dooring
引入了免费素材库和色彩搭配面板, 方便用户做页面设计参考:
素材库里列出了我们调研之后得出的的几个常用分类:
商业素材
生活类素材
自然类素材
插画类素材
配色方案目前提供了:
传统色
低调色
渐变色
色彩通用搭配方案
卡其色
用户可以参考配色方案搭建不同色彩风格的页面.
视图控件主要是方便用户可以更快捷的调整画布和控制画布中的元素. 我们都知道一旦页面中的元素变多之后, 我们在查找组件或者调整页面结构的时候就会变得非常麻烦, 比如页面过长, 我们需要上滑动才能定位到指定位置, 再比如页面元素过多, 我们想快速找到某一个元素并调整, 这样变得非常困难, 所以 Dooring
基于这些痛点做了一些改进和优化.
通过 Dooring
提供的画布控制面板, 我们可以快捷的切换画布大小, 或者通过手动输入自定义尺寸的方式来改变画布大小.
为了解决上述分析的第二个问题, Dooring
设计了图层管理面板.
我们可以通过图层管理面板轻松的管理画布中的组件, 比如:
显示/ 隐藏 组件
删除组件
调整组件排序(后期会迭代)
当然后期也会提供更强大的图层面板.
为了方便用户在画布中高效的创作, 快捷键是必不可少的, 所以 Dooring
也提供了快捷键的能力:
我们可以通过快捷键, 快速的实现复制, 删除, 粘贴图片等功能.
目前 Dooring
已支持如下文件解析能力:
DSL导入导出 (通过json快速生成页面和团队共享)
图片导入导出 (将海报或者图片快速拼装成可互动的H5网页)
PDF/DOC导入导出(将文件快速转化为可共享互动的网页链接)
下图是一个文件解析的案例:
以上演示可以看到, 搜索组件可以将商品组件的内容搜索出来, 进而实现了组件联动.
实现方案
我之前也分享了几种常用的组件通信方案, 如下:
props/$emit
子组件向父组件传值
eventBus($emit/$on
)
vuex / redux
$attrs/$listeners
provide/inject
具体的实现方式我在 低代码平台组件间通信方案复盘 有详细的介绍, 这里和大家分享一下我最近设计的一种组件间通信的方案 —— 自定义事件通信.
没错, 我们用的就是 CustomEvent
.
事件本质上是一种通信方式,一种消息机制,我们在遇到多对象多模块场景时,使用事件进行通信是一种非常有效的方式。在多模块化开发时,可以使用自定义事件进行模块间通信。
我们使用自定义事件也很简单, 就像我上面画的图一样, 我们只需要具备3个条件:
事件创建者
事件监听者
事件派发者
接下来我们用MDN的案例来说明如何使用它:
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");
// 创建一个新事件,允许冒泡,并提供要传递给“detail”属性的任何数据
const eventAwesome = new CustomEvent("awesome", {
bubbles: true,
detail: { text: () => textarea.value },
});
// 表单(form)元素监听自定义的“awesome”事件,然后在控制台打印传递的 text() 方法的输出
form.addEventListener("awesome", (e) => console.log(e.detail.text()));
// 当用户输入时,表单中的文本区域会分派/触发事件,并以自身为事件的起点
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));
以上就实现了一下自定义事件的监听和派发, 我们可以让不同的元素监听同一个事件, 并进行不同的逻辑处理.
同时它的兼容性也非常好, 主流浏览器都支持:
有了以上基础, 我们接下来来实现一下在低代码中基于事件的组件通信模式.
上面介绍了跨组件通信, 但是我们为了让业务层能更好的接入低代码或者零代码, 我们需要设计统一的数据源规范.
对于数据源的设计, 根据实际的业务需求, 我们可以分为静态数据源和动态数据源. 静态数据源是用户可以通过可视化的方式在低代码平台上创建的, 比如编辑数据表格等.
动态数据源是指用户可以自定义的请求第三方的数据服务, 组件消费数据源完全是动态调用的, 类似于我们传统开发时使用的ajax
请求.
当然为了保持普适性和接入的规范性, 我们需要提前约定数据源的字段和字段格式, 这样不同企业的业务数据都可以通过适配器来被通用的低代码组件消费. 这里分享一下 Dooring
的零代码创建数据源的模式:
数据源其实就是用户的一个通过可视化的方式来创建管理的数据库, 我们可以静态的录入数据, 也可以动态的通过接口获取数据:
然后我们在组件配置面板中就可以一键绑定数据源了:
接下来我们来实现组件通信的部分, 效果如下图:
首先在搜索组件中创建事件并派发:
const handleSearch = () => {
if(targetId) {
document.dispatchEvent(new CustomEvent(`search_${targetId}`, { detail: textRef.current.value }))
}
}
为了保持事件被监听的对象可控, 我们需要通过组件id来明确指定组件的监听目标, 所有事件名可以用目标id
+ 业务词
来组成.
接下来我们可以在商品组件来设计统一的监听:
useEffect(() => {
const eventName = `search_${id}`;
function handleDataChange(event: any) {
// 将数据传递给业务函数
handleSearch(event.detail);
}
document.addEventListener(eventName, handleDataChange)
return () => document.removeEventListener(eventName, handleDataChange)
}, [])
这样我们就能将 搜索组件的值通过 event.detail
方式传递给商品组件, 并在搜索按钮中触发事件的执行, 从而影响商品组件的业务函数的执行.
当然这只是一个简单的案例, 我们还可以利用这样的机制设计更复杂的通信, 比如事件队列, 让一个组件依次执行一系列的事件逻辑.
Dooring
为了更好的用户体验, 对用户行为做了埋点统计分析:
同时还可以通过搜索来发现用户行为路径的规律, 以便进行更科学的产品决策:
业务管理系统主要是为了管理平台数据资产和 Saas
用户的业务资产. 接下来我介绍几个核心的管理模块.
给用户分配等级:
会员权益配置:
我们可以在页面管理中直观的看到页面的访问数据信息:
并且可以一键预览自己做的页面:
如果你用 H5-Dooring
做了一个表单页面, 我们还能在页面管理中轻松看到表单的收集信息, 并支持一键导出为 excel
:
当然如果你用 H5-Dooring
配置了一个活动页面(比如大转盘抽奖, 九宫格抽奖活动), 你也可以在这里看到活动的数据:
组件管理可以方便运营人员快速的对组件进行上架和下架, 并对组件进行排序, 让用户更快速的找到自己常用的组件.
同时我们还能对组件进行权限设置, 让不通角色的用户拥有不同的组件操作权限.
模版管理主要是方便我们把优质的模版设置为精选模版, 供用户快捷的使用, 我们可以上架下架模版, 并同步到精选模版库中:
2024年Dooring
会持续优化用户体验, 上线更多实用组件和模版, 具体规划如下:
丰富组件物料(100+) 和模版库(1000+)
支持多人协同搭建能力
设计分层权限系统
应用级状态管理
AI辅助搭建 + 内容生成
升级表单搭建引擎, 支持分布表单搭建
上线页面分析面板, 赋能用户数据价值
如果你也有更好的想法和实践, 欢迎和我交流探讨.
github
地址: https://github.com/MrXujiang/h5-Dooring
在线地址: https://dooring.vip
2023年, 前端路上的开源总结(最新更新)
低代码平台组件间通信方案复盘
前端图形学实战: 从零开发一款轻量级滑动验证码组件(vue3 + vite版)