拖拽编辑器是一个基于公司前端典型页面系统上的一个项目,它用于改变传统的产品设计开发模式,减少设计、页面还原中间环节的成本浪费,真正做到设计开发一体化。
编辑器的核心功能是将页面元件/组件使用拖拽或是其它可视化编辑的方式来生成前端可用的静态文件代码,由于公司前端大部分项目与UI库使用的是vue技术框架,因此编辑器暂不考虑生成其它框架的代码成果物。
编辑器项目不包含自己的数据库,所有的数据/代码均以文件的形式存储在公司的gitlab服务器上。编辑器调用GitlabAPI来获取和存储数据。为方便前端开发过程中检索、拉取和使用代码,编辑器保存成果物时会将页面代码以单个.vue文件的方式保存在gitlab的对应项目仓库中。同样,编辑器也支持通过GitlabAPI读取.vue文件的gitlab地址获取对应的页面代码来进行二次编辑。
提到编辑器的输入和输出不得不详情说明下元件、素材与页面的概念。
元件是页面的最小组成单位,它可以是div、span、img等源生标签元素;可以是UI库中的基础组件,以ElementUI为例,如el-input、el-button等;也可以自定义的业务组件,如定义一个布局组件page-container。
拖拽编辑器需要接入元件库。元件库用于记录和存储页面所有元件的信息,每个元件信息单独存放在一个package.json中。元件库的结构如下:
#元件库的结构.├──Div│└──package.json├──span│└──package.json├──ElButton│└──package.json└──ElInput└──package.json以ElButton的package.json为例(仅列出部分属性作为示意):
这里额外说明下dependencies字段,其中包含了scriptUrl和linkUrl。一般在vue项目开发中,使用某组件常见的方式为先install该组件依赖,然后import引入改组件。但是编辑器采用umd动态引入的方式。组件可以在元件库中录入元件信息,scriptUrl为js文件地址,linkUrl为css文件地址,编辑器读取元件库时会根据umd信息动态引入文件,然后再编辑器中就可以正常使用了。
素材是由一个或多个元件组合而成,它是提供给编辑器的拖动材料。
素材库与编辑器本身解耦,它是托管在gitlab服务器上的文件仓库。
#素材库的结构.└──packages├──基础│└──基础元素│├──div.vue│├──span.vue│└──img.vue└──组件├──按钮│├──基础按钮.vue│└──主题色按钮.vue├──选择框│└──基础选择框.vue└──输入框├──基础输入框.vue└──文本域.vue一个素材就是一个.vue文件。素材文件不分代码是否复杂,内部元件数量是多少,只要想作为页面可拖动、可复用的材料都可以保存为素材文件。以下两个.vue文件均为素材:
页面就很好理解了,它是使用编辑完成页面编辑后,可以直接提供给前端开发人员使用的代码成果物。编辑器在保存时会将页面以.vue文件的形式保存在gitlab上对应的项目仓库中。前端人员在开发项目时,可以直接通过gitclone拉取整个项目的代码,也可以通过公司内部工具获取单个页面的代码文件到本地项目,省去静态页面开发的环节,十分的方便。
我们将刚才所说的元件库、素材库、页面库(项目文件库)整理一下,可以得到以下产品架构:
在介绍整体设计之前,我们先来看看拖拽编辑器制作页面的效果演示。
以下是拖拽编辑器制作一个简易的“百度”首页,为了方便演示,我们事先将一些素材给制作好了。
市面上的可视化编辑工具或是lowcode产品其实有很多。在设计之前我们调研了一些网上可用的产品:
总结了市面上产品的一些优劣和设计思路,我们对产品进行了一个初步的构想,然后经过多次内部评审与讨论,最终确定设计方向。这款拖拽编辑器遵循实用、易用、专业的设计思想,切实打造一款能有效优化开发流程,提升开发效率的前端工具。
编辑器以“输出开发人员可直接使用的代码”为第一目标。如果输出的代码,开发人员还需要大量修改的,那这就不是一个合适的产品。
设计师作为产品的第一用户群体,他们对前端知识的了解有限,在很多结构性、样式性的页面搭建时,与前端开发人员存在理解上的偏差(比如组件的属性设置)。如何降低学习成本,降低操作复杂度,提高用户体验,引导用户输出正确的页面代码是编辑器追求的第二目标。
市面上多数产品都只能支持基础的流式布局,显然公司这么多的中后台页面是不适用的。编辑器充分调研公司前端项目的代码特征,围绕内部UI组件库以及布局体系展开设计。
由于产品模块设计涉及到的内容多且杂,这边只介绍几个核心模块的设计思路
和众多的可视化编辑工具一样,编辑器页面分为操作和视图两个部分。
在设计拖拽编辑器的前期往往会陷入一个误区,认为拖拽就是将操作栏中的素材元素绑定拖放事件进行操作,其实并不是。我们要生成的页面是个流式布局而不是绝对定位。视图渲染页面是靠代码解析器生成的代码来渲染的,所以没有必要将整个素材元素DOM传给视图模块,只要告诉它控件代码片段的路径、在什么位置释放即可。所以,拖动的并不是DOM元素,拖动的只是信息。
如上图所示,编辑器左侧操作栏中展示所有可用的素材列表,此时的素材节点仅仅包含素材的名称与其代码文件所在的gitlab路径。用户拖动某个素材进入视图并释放后,编辑器再根据该素材的代码文件地址获取对应的代码片段。
这里详细解释一下该如何确定被拖动元素落在哪个元件容器中。
我们将这一设计抽象成“位置解析器”,它分为画板和虚拟元素块两个部分,画板是覆盖在视图上的一个操作层,所有的拖放操作均在画板上完成,这样不会因为视图上元件的一些特性(如mouseover事件等)产生什么负面影响。每一个视图上的元件都存在唯一标识,且都会在画板上生成一个虚拟元素块。换句话说,每一个画板上的虚拟元素块,都对应视图上的一个元件。虚拟元素块是一个div,相对于画板容器绝对定位,它的top、left、width、height值都和其对应的控件元素一样。这样一来,我们只要给每个虚拟元素块都绑定鼠标进出事件来监听拖动操作,就可以知道用户在那个元件容器中释放了。
拖动完成后,视图模块会根据素材所在的gitlab文件地址,通过调用GitlabAPI获取代码片段,然后和释放容器的标识一起,传入代码解析器。
代码解析器将传入的代码片段转换为AST数片段,然后根据父容器的标识,插入到指定的节点中去,组合成完整的AST树。打个比方,下图是将一个按钮拖动进入一个div后的代码处理示意:
代码处理部分,我们选取了一些核心的处理逻辑。
以el-button按钮组件为例,我们预先录入了type、icon和disabled三个属性,分别对应按钮的类型,图标和是否禁用。现在我们希望将一个默认样式的按钮改为主题色按钮,在代码中只需要在el-button标签上加一个type="primary"即可,在编辑器的设计流程为:
在页面制作的过程中,为了能保证输出代码的合理性,需遵从修改属性>>修改样式的原则,能修改属性达成的修改尽量不修改样式,比如上一章节说的修改主题色,其实本质上就是修改按钮元素的背景颜色、边框和字体颜色,但通过属性达成效果的代码才是我们正在想要的。
但是在制作一些自由度比较高的页面时,往往经常会修改元件的样式。编辑器的样式面板内置了一套样式表单,选用项目开发常用的CSS样式。大致分为以下4类:
这套样式表单采用可视化、图形化、文本语义化的方式让设计人员尽可能理解,并提供一些快捷操作尽量符合设计师的操作习惯。比如边距,可以采用图形化的方式更直观的看到要改变属性所对应的效果位置。
打个比方,我们要给一个div设置width:600px,用户可以在样式面板中的宽度项设置为600px,在编辑器的设计流程为:
除了上述介绍的一些设计外,编辑器还完成了以下功能,由于和之前的设计流程存在类似之处,就不详细展开介绍了。
在未来的版本中,我们同样也希望能加入更多的功能,去更大提升开发效率,包括:
拖拽编辑器的定位是作为一个能力工具,它可以向上封装成平台。为了方便设计师的使用以及管理,我们正在编辑器的基础之上开发一个在线页面设计平台(暂未有开源计划),支持设计稿的输出、展示和二次开发等功能。
如果你对如何使用可视化工具平台生成页面有兴趣或是也想开发一套拖拽编辑器,希望此文的一些设计思路对你有所帮助。
本文最主要讲解了一款输出vue页面的拖拽编辑器,以同样的设计思路也可以开发React和Angular等技术框架的页面。
我们希望通过搜集产品页面和构建流程的大数据,慢慢向智能化靠拢。最终实现能通过读取设计稿图片或是资源文件就生成可用的静态页面。“设计稿即代码”,相信最终的产品形态将不再拘泥于线上可视化构建平台,而是能提供智能化解析设计稿的能力。