可视化编辑器是干嘛的(html5可视化编辑器推荐)

去年上线的可视化编辑器 H5-dooring 至今已有一年的时间,期间有很多热心的网友和大佬提出了非常多宝贵的建议,我们也在一步步实现中,以下是几个比较典型的低代码可视化平台需求:

  • 出码能力(即源码下载功能)
  • 组件交互(即组件支持业务中常用的链接跳转,弹窗交互,自定义事件等)
  • 数据源管理(即用户创建的不同页面拥有共享数据的能力,不同组件之间也有共享数据的能力)
  • 组件商店(即用户可以自主生产组件,定义组件,接入组件数据的能力)
  • 布局能力(即用户可以选择不同的布局方案来设计页面)
  • 常用功能集成(页面截图,微信分享,debug能力)

上面的这些功需求已经在 H5-dooring 陆续实现了,在我之前的文章中也有对应的技术分享。但是为了让更多的人能低成本的拥有自己的可视化搭建系统,我们团队的大佬花了非常多的时间研究和沉淀,最近也开源了一款可视化搭建框架 dooringx-lib,我们可以基于它轻松制作可视化编辑器,而无需考虑内部的实现细节,接下来我就和大家分享一下这款可视化框架的使用方式和实现思路,同时也非常感谢 dooring可视化团队 各位大佬们的辛勤付出。前端:从零开发一款可视化搭建框架

dooringx

可视化搭建框架基本使用和技术实现

为了让大家更好的理解可视化搭建框架,我这里举几个形象的例子:

  1. antd —— antd-pro

可视化编辑器是干嘛的(html5可视化编辑器推荐)

GrapesJS 是一款国外的页面编辑器框架(详细介绍可参考我之前的文章 这款国外开源框架, 让你轻松构建自己的页面编辑器) ,那么 craft.js 就是它的上层应用框架。

  1. dooringx-lib —— dooringx

前端:从零开发一款可视化搭建框架

dooringx

dooringx-lib 是一款可视化搭建框架,同理 dooringx 就是基于 dooringx-lib 的可视化编辑器。

之所以要介绍它们的区别,是因为之前有很多朋友对这块概念理解的不是很清晰,在了解了可视化搭建框架 的 “内涵” 之后,我们开始今天的核心内容。

1.技术栈

在分享框架实现思路之前当然要自报家门,框架实现上我们还是采用熟悉的 React 生态,移动端组件库采用的众安团队的 zarm,编辑器应用层采用的 antd,至于其他的比如拖拽,参考线,状态管理,插件机制等都是我们团队大佬自研的方案。如果你是 vue 或者其他技术栈为主的团队,也可以参考实现思路,相信也会对你有一定的启发。

2.基本使用方式

在开始深入之前我们先看看如何使用这款框架,我们只需要按照如下方式即可安装使用:

npm/yarn  install dooringx-lib

同时我们还提供了基础的使用demo,方便大家在自己的工程中快速上手:

# 克隆项目# cnpmjsgit clone https://github.com.cnpmjs.org/H5-Dooring/dooringx.git# orgit clone https://github.com/H5-Dooring/dooringx.git# 进入项目目录cd dooringx# 安装依赖yarn install# 启动基础示例yarn start:example# 启动 dooringx-libyarn start# 启动 dooringx doc 文档yarn start:docyarn build

demo 的 github 项目如下:

可视化编辑器是干嘛的(html5可视化编辑器推荐)

上图就是我根据目前 dooringx-lib 的项目架构梳理的架构图,基本包含了搭建化编辑框架的大部分必备模块。为了保证框架的灵活性,我们还可以按需安装对应的功能组件,开发自定义的组件等。如下是一个基本的导入案例:

import {    RightConfig,    Container,    useStoreState,    innerContainerDragUp,    LeftConfig,    ContainerWrapper,    Control,} from 'dooringx-lib';

我们将整个框架拆分成了不同的模块,这些模块既相互独立又可以相互关联。完整的工作流程如下:

可视化编辑器是干嘛的(html5可视化编辑器推荐)

我们在上图可以看到左侧是我们的组件物料区,分为基础组件,媒体组件,可视化组件,它们的添加会统一放在 LeftRegistMap 数组中来管理,其基本结构如下:

const LeftRegistMap: LeftRegistComponentMapItem[] = [  {      type: 'basic', // 组件类别      component: 'button', // 组件名称      img: 'icon-anniu', // 组件icon      displayName: '按钮', // 组件中文名      urlFn: () => import('./registComponents/button'),  // 注册回调  },];

左侧组件支持同步导入或者异步导入。

如果需要异步导入组件,则需要填写 urlFn,需要一个返回 promise 的函数。也可以支持远程载入组件,只要 webpack 配上即可。

如果需要同步导入组件,则需要将组件放入配置项的 initComponentCache 中,这样在载入时便会注册进 componentRegister 里。

initComponentCache: {  modalMask: { component: MmodalMask },  },

4.2 如何定制左侧面板

可视化编辑器是干嘛的(html5可视化编辑器推荐)

事件可以细分为 注册时机 和 函数,组件内可以通过 hook 的方式来实现注册时机:

useDynamicAddEventCenter(pr, `${pr.data.id}-init`, '初始渲染时机'); //注册名必须带id 约定!useDynamicAddEventCenter(pr, `${pr.data.id}-click`, '点击执行时机');

useDynamicAddEventCenter 第一个参数是 render 的四个参数组成的对象。第二个参数是注册的时机名,必须跟 id 相关,这是约定,否则多个组件可能会导致名称冲突,并且方便查找该时机。

注册完时机后,我们需要将时机放入对应的触发位置上,比如这个 button 的点击执行时机就放到 onclick 中:

<Button    onClick={() => {eventCenter.runEventQueue(`${pr.data.id}-click`, pr.config);    }}>    x.dooring</Button> 

其中第一个参数则为注册的时机名,第二个为 render 函数中最后一个参数 config

  1. 函数注册

函数由组件抛出,可以加载到事件链上。比如,注册个改变文本函数,那么我可以在任意组件的时机中去调用该函数,从而触发该组件改变文本。

函数注册需要放入 useEffect 中,在组件卸载时需要卸载函数!否则会导致函数越来越多。

useEffect(() => {const functionCenter = eventCenter.getFunctionCenter();const unregist = functionCenter.register( `${pr.data.id}+改变文本函数`, async (ctx, next, config, args, _eventList, iname) => {  const userSelect = iname.data;  const ctxVal = changeUserValue(   userSelect['改变文本数据源'],   args,   '_changeval',   config,   ctx  );  const text = ctxVal[0];  setText(text);  next(); }, [  {   name: '改变文本数据源',   data: ['ctx', 'input', 'dataSource'],   options: {    receive: '_changeval',    multi: false,   },  }, ]);return () => { unregist();};}, []);

函数中参数与配置见后面的函数开发。

4.5 右侧面板开发

可视化编辑器是干嘛的(html5可视化编辑器推荐)

右键菜单可以进行自定义:

// 自定义右键const contextMenuState = config.getContextMenuState();const unmountContextMenu = contextMenuState.unmountContextMenu;const commander = config.getCommanderRegister();const ContextMenu = () => { const handleclick = () => {unmountContextMenu(); }; const forceUpdate = useState(0)[1]; contextMenuState.forceUpdate = () => {forceUpdate((pre) => pre + 1); }; return (<div style={{            left: contextMenuState.left,            top: contextMenuState.top,            position: 'fixed',            background: 'rgb(24, 23, 23)', }}> <div            style={{ width: '100%' }}            onClick={() => {                    commander.exec('redo');                    handleclick();            }}        >            <Button>自定义</Button> </div></div> );};contextMenuState.contextMenu = <ContextMenu></ContextMenu>;

先拿到 contextMenuState,contextMenuState 上有个 unmountContextMenu 是关闭右键菜单方法。所以在点击后需要调用关闭。同时上面的 left 和 top 是右键的位置。另外,我们还需要在组件内增加强刷,赋值给 forceUpdate,用于在组件移动时进行跟随。

4.7 表单验证提交思路

可视化编辑器是干嘛的(html5可视化编辑器推荐)

表单验证提交有非常多的做法,因为数据全部是联通的,或者直接写个表单组件也可以。在不使用表单组件时,简单的做法是为每个输入组件做个验证函数与提交函数。这样是否验证就取决于用户的选取,而抛出的输入可以让用户选择放到哪,并由用户去命名变量。

在点击提交按钮时,调用所有组件的验证函数与提交函数,使其抛给上下文,再通过上下文聚合函数聚合成对象,最后可以通过发送函数发送给对应后端,从而完成整个流程。我们可以在 dooringx 中试下这个demo。

另一种方式是可以专门写个提交按钮,固定了参数,以及部分规则,比如规定在页面中的所有表单都会被收集提交。

那么我们可以利用数据源,将所有表单输出内容自动提交给数据源,最后的提交按钮按数据源规定格式的key 提取,发送给后端。

后期规划

后期我们还会在产品功能方面持续迭代优化,如果大家有好的建议, 也可以随时和我们交流, 也欢迎在 github 上积极提 issue。

如果大家对可视化搭建或者低代码/零代码感兴趣,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端真正的技术。

github: dooringx | 快速高效搭建可视化拖拽平台团队:Dooring可视化团队

(0)
小多多的头像小多多创始人

相关推荐

发表回复

登录后才能评论