本文将带大家一起探索低代码开发的核心 —— 页面设计器
。
我们知道,低代码开发平台都是通过拖拉拽可视化的页面设计器进行页面开发的,在这一章节,我们来探索一下页面设计器的实现方式。下图中,我们截取了几款优秀的低代码产品的页面设计器界面。
image.png
可以看到,大多数的页面设计器都包含了如下所示的几个区域:
操作栏
,我们可进行页面的保存、预览、查看json信息、查看代码等操作;组件列表
,当然也可以添加一些切换,让我们的左侧区域支持查看页面树信息、配置数据源等其他操作;画布
区域,我们可以将左侧的组件拖动到画布中,当然也支持画布中组件的赋值、删除等操作;属性配置
区域,当我们在画布中选中某个组件时,可以在右侧的属性配置区域罗列出当前组件可支持动态配置的属性,修改了属性后可以在画布中看到对应组件的样式变化。图片截取自宜搭,仅用于区域展示,与本篇内容无关
下面,我们按上述的区域划分来看一下页面设计器区域都是如何实现的。
首先,我们来看一下左侧的组件列表,列表中的每个组件,我们都需要使用一段json
来进行描述,这段json
我们将它称之为 元数据,元数据中描述了当前组件的中文名称,在列表中显示的图标及描述,和组件可进行配置的一些动态属性。我们以输入框组件为例,它的元数据大致可以定义为如下的样子:
{
code: "MyInput",
name: "输入框",
desc: "输入框的描述",
icon: "input",
props: {
name: "字段名称",
label: "label名称",
labelCol: "",
wrapperCol: "",
required: false,
}
}
复制代码
那么左侧的组件列表实际上就是这样的一个元数据对象组成的数组遍历而来的。
再来看一下将左侧组件列表的组件拖动到画布是如何实现的。拖动又分为顺序排列布局的拖动及自由布局拖动。顺序排列布局的拖动是指拖动到画布中的组件是自上而下顺序排列的,可以通过拖动调整上下顺序,当然我们也可以增加分栏这样的布局类型组件,实现组件的左右排列;自由布局拖动是指拖动到画布中的组件位置是自由的,我们松开鼠标的位置,就是这个组件在画布中的位置。考虑到我们主要服务的是B端项目,需要尽可能的使用户体验保持一致,这里呢我们采用的是顺序排列布局的拖动。这样用户拖动设计出的页面差异性不会太大,页面布局上又相对规整。
拖动插件由于我们是vue
技术栈,选选择了vuedraggable
插件。像react
技术栈也有类似的插件,大家很容易可以搜索到。对于vuedraggable
组件的安装及说明这里我们就不赘述了,直接上demo。
<template>
<a-row style="padding: 20px">
<a-col span="10">
<h3>列表区域</h3>
<draggable
class="dragArea list-group"
:list="list1"
:sort="false"
:group="{ name: 'people', pull: 'clone', put: false }"
>
<div class="list-group-item" v-for="element in list1" :key="element.name" >
{{ element.name }}
</div>
</draggable>
</a-col>
<a-col span="10" offset="4">
<h3>目标区域</h3>
<draggable
class="dragArea list-group"
:list="list2"
group="people"
>
<div class="list-group-item" v-for="element in list2" :key="element.name" >
{{ element.name }}
</div>
</draggable>
</a-col>
</a-row>
</template>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable
},
data() {
return {
list1: [
{ name: "组件1", id: 1 },
{ name: "组件2", id: 2 },
{ name: "组件3", id: 3 },
{ name: "组件4", id: 4 }
],
list2: [
{ name: "画布组件1", id: 5 },
{ name: "画布组件2", id: 6 },
{ name: "画布组件3", id: 7 }
]
};
}
};
</script>
<style scoped>
.list-group-item {
height: 30px;
border: 1px solid #888888;
}
</style>
复制代码
呈现的样式如下图所示:
image.png
上面的demo定义了两个区域,列表区域和目标区域,并定义了两个数组,list1
和list2
。列表区域和目标区域分别使用list1
数组和list2
数组进行遍历渲染。当我们将列表区域的组件3
拖动到目标区域时,我们打印list2
变量的数据,就会 发现组件3
被复制到了list2
中,即复制到了目标区域。细心的小伙伴已经发现,唉!这不就是我们页面设计器组件拖动到画布中的实现方式嘛!是的,设计器中的拖动原理就是这样简单。
支持拖动的区域需要使用<draggable>
组件进行包裹,<draggable>
组可以添加onAdd
、onStart
、onEnd
及move
事件回调函数,我们可以在这些事件中添加一些我们需要的逻辑。例如,我们可以在onAdd
函数中对我们添加到list2
数组列表中的对象动态的添加一个唯一值id
,用于我们区分同一个页面拖入两个相同组件的情况。
下面让我们对上面的简单demo稍加改动:
列表区域
list1
数组的中的每一项修改为我们之前定义好的组件元数据。画布区域
我们现在知道,画布中的列表实际也是通过组件元数据数组进行渲染的,而每个原数据项都对应了一个真实的组件,这样我们只需要将元数据项替换成UI组件进行渲染就可以了。在代码中大致是如下的样子:
<template>
<div v-for="item in list2" :key="item.id">
<my-input v-if="item.code === 'MyInput'" :data="item"/>
<my-select v-if="item.code === 'MySelect'" :data="item"/>
...
</div>
</template>
复制代码
哈哈,有的小伙伴已经看出来了,这样写不太优雅,我们用动态组件优化一下。
<template>
<div v-for="item in list2" :key="item.id">
<component
:data="item"
:is="item.code"
/>
</div>
</template>
复制代码
2 . 画布中组件支持删除、复制、拖动操作
image.png
拖动
我们的demo示例中,目标区域list2
是支持可拖动排序的
复制
我们已经知道,画布中的组件是通过list2
遍历渲染出的。当点击复制操作时,只需要将当前被点击复制按钮的组件所对应的元数据添加到list2
中就可以了。这里需要注意,在复制元数据的时候,我们需要将id
属性值进行累加计算,这样才能区分被复制的组件和复制生成的组件。
删除
同理,删除操作,我们只需要将list2
中的组件通过被复制组件id
进行过滤就可以了。
到这里,有些小伙伴可能有些疑问,目前。组件拖动到画布进行显示已经问题不大了。那么组件中是否可以再拖入组件,就像我们在vue
编程中进行组件的嵌套一样呢?通过一些优秀低代码产品,我们可以发现,他们组件列表都是进行分类显示的,布局类组件就是这样一类可以在组件内部再进行拖动的组件了。这类组件包括栅格组件、容器组件、多页签组件、卡片组件等。我们知道,list2
就是最终页面渲染的组件列表,它是一个对象数组的数据结构,为了让它支持嵌套组件,我们需要在组件的元数据对象上增加一个属性,这个属性用来描述该组件下又嵌套了哪些组件,我们就命名这个属性为children
。那么,包含嵌套组件的页面数据大致就是下面所示的样子。
[{
code: "MyCard",
name: "卡片",
props: {
...卡片组件相关配置属性
},
children: [{
code: "MyContainer",
name: "容器",
props: {
...容器组件相关配置属性
},
children: [{
....
}]
}]
}]
复制代码
为了满足嵌套组件的需求,我们需要做两个方面的调整。
我们在容器类组件内部再次引用<draggable>
组件,组件的list
参数值为容器组件元数据的children
数组,然后在draggable
组件内部使用插槽将children
进行渲染。容器组件的模板大致是下面的样子
<template>
<div>
<draggable class="dragArea list-group" :list="data.children" handle=".drag-icon"
@add="handleAdd" @start="handleStart" @end="handleEnd">
<slot>
</slot>
</draggable>
</div>
</template>
复制代码
2 . 画布能够按照嵌套组件进行显示
对于无嵌套组件的页面,渲染时我们只需要对list2
数组进行遍历渲染就可以了。但是具有嵌套组件的页面这种简单的for
循环就无法满足了,我们需要对组件进行深层循环遍历。例如下面的实例代码。
export default {
props: {
data: Array,
},
methods: {
renderTree (list, id) {
return list.map((item) => {
return (
<content-item data={item} id={id} >
{item.children && item.children.length ? this.renderTree(item.children, item.id) : null}
</content-item>
);
});
}
},
render: function (h) {
return (
<div>
{this.renderTree(this.data)}
</div>
);
}
};
复制代码
这样我们就扫清了拖动的一切障碍。下面,让我们把目光聚焦到页面设计器右侧的属性配置区域。
其实到这里,很多小伙伴应该已经大致能够推理出属性配置后画布中组件根据配置进行显示的联动是如何进行的了。原理同样非常简单。我们可以对画布中的组件添加点击事件,当点击某个组件时,我们能够获取到当前点击组件的组件类型,例如输入框、下拉选择等等,针对每一种组件,我们已经提前在元数据中的props
属性定义了这个组件能够进行动态控制的参数,我们只需要将这些参数以合适的表单形式展示在右侧的属性配置区域就可以了,例如,按钮组件的props
中有一个text
属性,用来控制按钮的显示文案,那么我们就在右侧属性控制区域用一个输入框来做为控制这个属性的表单形式,当修改数据时,我们找到list2
中该组件所在的元数据对象,然后将该对象中props
属性中text
属性值修改为输入框中的内容。每个组件都会接受这个组件对应的元数据props
参数,然后根据参数值进行渲染。例如按钮组件,现在按钮的文案时,我们可以使用props.text
进行显示。
从上面的文章中可以看出,一个页面实际就是用一段带有层级结构的json
来进行描述的。
保存时实际就是将这段json
进行保存操作,我们可以将json
存储到数据库中。
在上面讲解画布区域时,我们已讲到组件如何通过json进行渲染。预览以及真实的页面渲染实际和画布中组件的展示实现原理完全一致。其中的区别有两点:(1)画布中的组件不支持交互操作,这里,我们需要屏蔽画布中组件的交互操作。我们可以通过css
中的after
伪类,设置content
为""
来实现。(2)画布中的组件需要包裹一个div
,这个div
包含了复制、删除等功能。
其实整个页面设计器的核心就是json
,其它各种功能也都是围绕json
进行。我相信大家仔细读完这篇文章,再看其它功能时也可以推断出其实现的原理。
好啦,至此页面设计器的组件列表、画布和属性配置三个区域的联动我们就都实现了。目前,我们的页面设计器设计出的界面还是静态的,画布中的组件也都是独立而毫无关联的。在真实的业务场景,组件间的通讯是非常常见的。在后面的章节中,我们讲会重点介绍低代码中如何进行 组件间通讯
的配置。我们一起手拉手,搭建自己的低代码平台~!
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/eZyxA1ijYyvQPtdab11QEQ
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。