头图

啥是页面设计器?

就像用 Axure 画原型那样简单拖动几个组件,然后再设置一下,就开发好了一个系统页面,可以查看数据、操作数据、可以使用的、真正的页面。

是的,这就是低代码平台中的页面设计器,这我就好奇了,这样的页面设计器是怎么设计出来的呢?设计的思路与原则是怎样的呢?

设计可以开发出页面的设计器与一般系统的功能页面可是不一样的,后者相对而言是确定的,具体有哪些功能,有哪些交互,需要调用后端哪些接口,整体效果是可控的。而对于设计器页面,设计出的最终页面效果是用户来确定的,怎么才能满足用户可以实现他的前端页面交互、前后端数据交互呢?

临危受命,准备干活!

当时,我们公司将产品定位于帮助业务人员和开发人员高效快速地开发出各种企业模板应用和各种复杂业务应用,解决各种定制化场景需求,这样就必须要求设计器做到灵活性高、扩展性高,同时易用性也得高。

道理我都懂,确实很牛 X,如果是让别人去设计,我肯定会说舞台很大,好好表现。然而不幸的是,这个任务落到了我的身上,哈哈哈=-=

真的是让人头大,作为刚刚接触到低代码平台的小白,不说无从下手吧,也可以说让人摸不到头脑!

冷静了一阵子后,想了想,事情还是得做呀!

投石问路,竞品分析!

作为一个产品人,遇上毫无头绪的需求,第一反应是干嘛?那必须得是竞品分析呀!

是的,我立马找了市面上为数不多的低代码平台,准备仔仔细细地琢磨琢磨,当时的低代码平台都比较简单,上手都很快,差不多一天时间就研究得七七八八了并做了详细的分析记录。

可是做完竞品后,内心有一点小小的失望,发现低代码平台产品与自己预想中的差异有点大,市面上的低代码平台主要以表单、表格驱动为主,集成封装程度较高,虽然可以满足一般的数据增删改查和简单的业务流程,但是很难满足复杂业务应用各种定制化的需求,更不用说面向 C端用户的应用页面。不过也是,毕竟当时低代码平台的概念在国内也才刚刚兴起。

后来仔细一想,这反而是一件好事,说明我们的想法别人还没有尝试过,这条路说不定舞台真的很大!

此路不通,另辟蹊径!

竞品分析效果不是很好,我决定换一种方式了,设计器不就是要设计出各种复杂的应用页面吗?我研究一下复杂的业务应用中有哪些页面,哪些功能不就 OK 了吗。

想到就去做,我立马找了市面上主流的一些 ERP、CRM 、OA 等企业内部管理系统,主要研究系统中的核心功能页面,看能不能从这种复杂的页面中找到一些共性,包括页面中的主要部件、页面交互、接口调用等等。

你还别说,你还真别说,研究了一段时间后,还真的有所收获,最后大言不惭地说了一句:好像也不过如此,没有那么复杂嘛=-=

下面详细分享一下当时的分析和设计思路,开始我的表演。

因为时间有点久远了,中间也迭代了多次想法,这里就不用最原始分析的资料,我在阿里云和钉钉后台分别找了两张页面截图,借此说明当时的分析思路。

首先来看第一张阿里云控制台中的云服务器概览功能页面。

image.png

这种页面结构在 B 端系统中是十分常见的,也极具有代表性。页面是由不同的区块组成的,我在图片上用数字标注了不同的区块,每个区块之间相对独立,但彼此又有联系,有的是交互上的联系:

  • 比如区块 ② 是一个标签页,切换不同的标签下面显示不同内容,区块 ③ 是一个列表,点击不同的列表项,右侧显示不同的内容 ;
  • 有的是数据传递上的联系,比如区块 ④ 是日期查询, 执行查询后区块 ⑤ 显示满足条件的统计数据;
  • 当然我们多研究一点页面就会发现,交互联系和数据传递联系是可以同时存在的,而且在大多数场景中,这两者是同时存在的;
  • 区块④ 上面的静态文本虽然我没有用数字标准,其实也可以作为一个区块;
  • 但是区块 ① 有点特殊,它是系统功能导航,一般 B 端系统里都有功能导航框架,有左侧的,有顶部,有 L 型的等等,所以严格意义上说它并不属于页面的一部分,我们可以单独提出一个概念来表达它,这里不详细展开,后续可以专门写一篇文章,这里面也大有门道哦。

经过上面的一分析,我们再回过头来看并总结一下:

这个页面就是由几个区块组成的,区块之间可以点击交互、可以数据传递。一句话就概括了,没有错,就是这么简单。

可能有人要说了,这个区块里面的功能你都没有分析呢,你就说简单?

好像说的也啥毛病=-=,但我们从页面顶层设计时,可以先忽略局部细节问题,这就好像高中学物理受力分析时,先用整体分析法,忽略物体内部作用力,得到整体受力结果后,再分析单个物体,这里面的设计思想应该是想通,所以后面再讨论区块里面的功能问题。

好了,有了页面的整体结构后,再看第二张图,是不是就容易理解多了,这里就不再做重复分析了。

image.png

大刀阔斧,准备开干!

由上面的分析得到了结论:这个页面就是由几个区块组成的,区块之间可以点击交互、可以数据传递。到这里就必须正视区块了,区块到底是什么?我们应该怎么定义它?我们先看区块有哪些特点:

  1.  会显示在页面上;
  2.  会有特定的功能,比如多标签切换、表格展示数据、筛选数据等等,反正是为了解决特定场景功能;
  3.  可以点击;
  4.  会输出数据;
  5.  可以接受数据。

当然不是区块必须同时这些功能,有些区块可能只有其中一部分功能。

到这里,我觉得用“区块”来表达已经不是很贴切了,所以急需换一个更合理、更好理解、更通用的概念,“组件”应运而生!!!

为了更合理地表达,给组件加一个概念定义:组件是将页面中的可重用部分抽象为独立的、功能完备且具有自我样式和行为、支持输入与输出的单元。

组件属性配置

首先要明确一点,组件是为了解决特定场景需求的,所以在组件内部会封装一定的功能,比如表格组件会展示数据、支持分页、添加按钮等,筛选器组件支持设置筛选字段,筛选方式等等,同时为了给用户绝对的灵活性,需要提供丰富的配置项。

image.png

image.png

组件本身功能可以通过内部封装加配置项的方式来解决,那怎么解决组件之间的交互联动和数据传递联动呢?这是一个问题,这让我想起了在网络被发明之前,计算机都只是独立的个体,并不能直接完成资源共享,有了网络之后才算真正地进入计算机时代!

前端组件联动

当我在考虑组件之间的联动问题时,不由得想到面向对象编程思想中的“类”,“类”不仅相对独立,“类”与“类”之间还可以相互调用、进行数据传递。我们一起来看下“类”有哪些特性:

  • 成员变量,类内部定义的变量,可以定义私有、公有;
  • 构造函数,默认无参 ,可以定义有参构造函数,在创建类实例对象时使用;
  • 成员/静态函数,类实例或类调用,负责具体的逻辑,函数内部可以使用类成员变量、可以利用函数对外输出类的成员变量。
public class Person {
    // 成员变量
    public String name;
    private int age;
    private String email;
 
    // 无参构造函数
    public Person() {
    }
  
    // 带参构造函数
    public Person(String name, int age, String email) {
        this.name = name;
        this.age = age;
        this.email = email;
    }
  
    // 类的成员函数
    public String doSomething() {
        return "XXX";
    } 
}

借鉴“类”的特性,于是,我们可以对组件有以下的定义:

  • 组件变量:组件内部运行时对处理数据的变量,类比于“类”的成员变量;
  • 组件函数:运行组件的入口,组件函数可以携带参数,也可以不携带参数,类比于“类”的构造函数;
  • 组件事件:组件运行时的点击对外输出的事件,可以通过组件事件对外输出组件变量,类比于“类”的成员函数。

每个组件的开发者,需要定义组件的组件变量、组件函数、组件事件,当然这三者不是必须同时存在,某些特性在一些组件中可以没有。

这样就可以做到组件联动了吗?怎么说得云里雾里的。

是的,是可以的,举一个跟上面阿里云控制页面差不多的功能场景:输入日期筛选后,下面的表格显示满足条件的数据

我们做一下需求分析,在页面需要一个筛选器组件(用于筛选)和一个表格组件(用于展示数据),筛选器组件和表格组件定义的组件的属性见下表:

image.png

我们用一句简单的语句就可以实现这个需求了:在筛选器组件的组件事件(执行查询后)添加语句:表格组件.刷新表格(筛选器组件.筛选条件)

OK 了,简单吧

这样, 在实现组件自身的功能的同时定义好每个组件的组件变量、组件函数、组件事件,这样可以达到组件之间可以任意组合,组件交互联动,数据联动也不在话下!

基于上面的机制,我们开发一个稍微复杂一点的订单管理功能,功能特性有:

  • 支持按订单的金额、下单时间、订单编号等筛选订单明细
  • 统计每日订单消费金额、每月汇总订单消费金额
  • 展示订单明细,支持新增订单、编辑订单、查看订单详情、删除订单。
  • 筛选、统计、订单明细之间要相互联动,包括新增/编辑/删除订单也是刷新订单明细和统计。

具体效果可以查看下图

演示5.gif

看着有点复杂功能,其实我们利用几个组件和几句语句就开发好了,展示部分截图

image.png

image.png

当然上面使用的都是一些简单的语句,后来随着功能的扩展,类比于一般的编程语言,我们逐步加入了条件判断语句、循环判断语句、声明变量语句等等,可以看下图简单了解一下,这里就不详细展开。

image.png

前后端数据联动

有细心的小伙伴可能已经发现了,你上面的一顿分析都是前端组件之前的联动,如果前端需要调用后端某个接口怎么处理呢,比如我在表格组件中添加了一个按钮,这个按钮需要执行后端接口的逻辑,那又怎么实现呢?

这是一个好问题,首先我们在实现某些组件时会封装调用特定的后端接口,比如表格组件展示数据,我们会调用查询数据接口,表单提交数据会调用新增数据接口,但是这解决不了前端调用用户自己编写的接口。

这个过程中我们想了很多办法,比如前端事件触发后台工作流?专门开发一个前端组件调用后端接口?利用数据表事件、定时任务变相地解决这个问题?等等方案,但不是很优雅,不是很符合我们编程语言中的使用习惯

后来我们将用户自己编写的后端接口放在服务下,就像传统编程语言中编写某个类下的函数一样,前端组件调用后端接口就按照执行指定的格式调用就好,比如 XX 服务.XX 函数,可以看下图中的语句,这个设计也是经历过很长的积淀才形成的,完美而优雅,这里就不再详细分析了,后续专门出一篇文章介绍,这个过程也是美妙又有趣的!

image.png

image.png

略微小结

至此,我们很完美地完成这项任务,设计出了一个灵活性强、易用性高的前端页面设计器,文章写出来看着轻松,可是其中的过程却是异常艰辛,中间走了不少弯路,试了不少错,幸运的是,结果是好的。在这次设计过程中,我也总结了几点设计经验与大家分享:

  • 分析问题本身,探索问题本质,透过现象看本质;
  • 先顶层设计,再考虑细节;
  • 经典永不过时,多向经典的编程思想借鉴学习,设计思想都是互通的;
  • 不断迭代、不断否定,追寻问题的最优解。

以上就是我的分享,如果你对低代码或者产品设计感兴趣,可以在评论留言或者私我,我们下一期再见。
极态云官网


一身肌肉的绿茶
1 声望0 粉丝