低代码作为前端一个比较热门的方向,讨论度或者热度都算是拉满了。
如果你想了解低代码,可以在网上找一些相关的网站。像阿里等公司都有开源的项目和在线体验。
但是因为他们的代码比较牛逼,其实没有那么通俗易懂。
那博主是想,通过一系列文章的讲解,从零实现一个低代码的工程,包括设计态,运行态,组件以及后端服务。
那看到这篇文章,你肯定想知道会实现出一个什么样的低代码工程。下面是最终的实现效果:
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
XinBuilder 点击跳转
点击快速开始,第一次加载可能会慢一些,等待即可,然后输入默认的账号密码,就可以看到要实现的低代码平台了。
当然,这是我实现的第一版,而从这篇文章开始,我准备使用TS进行重构,所以可能会有一些差异。
那博主准备写的这一系列文章,主要使用React框架 +Hook 做基础开发。
使用AntD来作为项目的基础组件。
因为博主是前端开发,所以后端服务选择了Nest,数据库选择了MongoDB,当然博主后端能力比较菜,只能实现接口的增删改查。
当然整个系列,肯定是前端开发为主,甚至前面可能都不会涉及到数据库和后端服务。
如果选择了这一套系列文章进行学习,那么最好是一边看文章,一边写代码。同时还要看着上面的在线例子。
XinBuilder 点击跳转
其实作为偏教程的,还是看视频最过瘾,但是博主没有录过视频,所以尽量将文章讲的清楚一点,多配一点图片。OK,垃圾话就说这么多,从后面开始,就要实现整个工程了。
现在,开始吧!!!!!!!!!!!!!!!!
做这个教程,肯定是希望去实现低代码,并不关心Webpack配置啥的了。
所以这里我们直接使用create-react-app这个指令,快速创建一个前端项目。
create-react-app XinBuilder --template typescript
当然你可以叫LongBuilder,也可以叫ShengBuilder,都行,因为我名字最后一个是Xin,所以就叫XinBuilder了。
创建好项目后,把该删的都删了,最后只需要留下App.js和index.js即可。
因为项目的体积比较大,所以建议读者,还是用过Git去管理项目。
OK,现在我们在src的目录下,创建一个pages文件夹,用来保存所有的路由页面。
然后在pages里面,创建一个builder文件夹,用来保存我们设计态的页面。
创建好的目录结构是这样的:
在项目里面,我们需要用到AntD的组件,所以我们再安装一下AntD。
npm install antd --save
现在准备工作就已经做好了,准备开始开发了。
你可以进入到 XinBuilder 点击跳转例子中,创建一个页面或者选择某个创建好的页面,点击编辑页面,进入到设计态。
可以看到,在设计态里,主要分为了三个部分。
左侧是用来展示组件的,中间是画布区,右侧是用来配置组件的属性样式的。
那我们在builder目录里面,也应该有这三个部分,所以我们现在实现一下这三个部分的结构。
不知道我上面这张图够清楚吗,在App里面引入Builder组件,在Buidler组件中引入
LeftCom, MainCom, rightCom三个组件。
这样我们的页面就会将这三个部分展示出来了,就是三个文本靠在左侧展示,这里我就不再把图片贴出来了。
因为作为一个项目,顶部栏有的话还是比较美观的。
当然你可以自己去实现想要的效果,如果对这部分不感兴趣可以跳过,而我就在builder目录下新增一个designTop目录,用来实现顶部栏。
XinBuilder\src\pages\builder\designTop\index.jsx
import './index.css'
export default function DesignTop() {
return (
<div className='designTop'>
<span className='title'>XinBuilder</span>
</div>
)
}
XinBuilder\src\pages\builder\designTop\index.css
.designTop{
position: absolute;
height: 10%;
color: rgb(211, 202, 202);
width: 100%;
z-index: 1000;
/* border-bottom: 1px solid rgb(209, 203, 203); */
box-shadow: 0 0 2px 2px rgb(209, 203, 203);
background-color: #ffffff;
}
.designTop .title {
color:rgb(192, 190, 230);
position: relative;
left: 100px;
font-size: 28px;
top: 15px;
font-style: italic;
font-weight: bold;
}
这里面可能会有人问一个问题,为什么要对顶部栏进行定位,还是通过absolute,这样不会使顶部栏脱离文档流吗?
这是因为,在整个低代码平台中,我的设计理念是,整个屏幕都是画布区,虽然默认展示只有中间的一部分,但是可以通过将上面的顶部栏折叠,然后扩大画布区的范围。将顶部栏设置为脱离文档流,方便我折叠它。(不过目前对我们实现的效果没有影响)
leftCom,rightCom,还有mainCom因为顶部栏脱离文档流,被遮住了。
当然你如果不喜欢这种方式,也可以用自己的喜好来。
在XinBuilder 点击跳转里面,可以看到,设计态的左侧是一堆组件。那我们第一步要实现出什么效果呢?
这里我们先实现出,左侧的组件可以拖拽的效果。这里我们先拿一个Button组件举例子。
在leftPart下,我们新建一个component文件夹用来保存组件,staticUtil用来保存公共方法。在component下新增两个文件夹,button和input。分别代表按钮组件和输入框组件。
这里面插一句,在左侧的这个区域,和组件本身没有什么关系,就是用来纯展示,可以拖拽就可以。那在leftPart里面,我们怎么能够拿到所有的组件呢?
XinBuilder\src\pages\builder\leftPart\component\index.js
import Input from "./input";
import Button from "./button";
export {
Input,
Button
}
为了方便好看,我们在index.html中,将body的背景颜色设置为灰色。
<body style="background:#f2f2f2">
OK,现在组件已经准备好了(假组件,只是个文本哈)。我们动手实现项目的左边部分。先实现出来样式和基本组件。
看效果,是一个Tab页签,下面跟着组件。
插入一下,上面的就不改了,命名错误,都是tsx和ts,写成js和jsx了,看到这请修改一下
XinBuilder\src\pages\builder\leftPart\index.tsx
import './index.css'
import { Tabs } from 'antd';
import type { TabsProps } from 'antd';
export default function LeftCom() {
const renderComponet = () => {
return <div></div>
}
const items: TabsProps['items'] = [
{
key: 'component',
label: <div style={{fontSize:'18px',width:'100px',textAlign:'center'}}>组件</div>,
children: renderComponet(),
},
{
key: 'data',
label: <div style={{fontSize:'18px',width:'100px',textAlign:'center'}}>组件</div>,
children: 'Content of Tab Pane 2',
}
];
const onChange = () => {
}
return (
<div className='leftCom'>
<Tabs defaultActiveKey="1" items={items} onChange={onChange} />
</div>
)
}
XinBuilder\src\pages\builder\leftPart\index.css
.leftCom {
width: 20%;
position: absolute;
top: 10%;
background-color: white;
height: 90%;
}
简单说一下这两个文件的代码,在leftCom组件里,我们返回一个Tab页签,其中一个是组件,另一个是数据。
目前我们只关心组件,所以对于数据这一块,我们先不管了。
现在我们要实现renderComponet方法,该方法主要是用来实现左侧组件列表的。
之前我们说过,怎么能拿到component下所有的组件,是通过export导出的,在leftCom里面,我们可以通过import将所有的组件拿到。
import * as components from './component'
这里注意一下,components是一个对象,key就是我们在component下index.js导出的组件名。**value是组件本身,也就是一个函数!!!**
在renderComponent中,我们通过拿到的components,去遍历生成组件。
const renderComponent = () => {
return <div>
{
Object.keys(components).map(name => {
return <div draggable key={name} className='componentItem'>
<div style={{display: 'inline-block'}}><span>{name}</span></div>
</div>
})
}
</div>
}
.componentItem{
width: 80px;
height: 30px;
margin-top: 10px;
margin-left: 15px;
border: 1px solid rgb(187, 181, 181);
border-radius: 4px;
padding: 10px;
}
在最外层增加一个draggable属性,这样就可以拖拽了。
现在我们实现出的效果应该是这样的:
这两个组件可以拖拽,但是拖拽的时候,鼠标附近会有一个禁用的符号。
这个先不要管,我们后面实现画布区的时候会解决。
第一节就先说到这里,在github上,我提交了这部分的代码,如果有差错的地方可以进行查看比对。
https://github.com/TeacherXin/XinBuilder2
commit: 第一节:初始化项目,实现左侧组件列表
当然,如果上面的内容已经掌握并且实现了,可以多实现几个组件做基础。例如头像,图标,单选框等组件,不用关心具体怎么实现,只需要在components文件夹增加几个组件,内容就是一个文本即可。
左侧组件列表的样式也可以自行调整,例如在组件下面加个图标?这些样式调整我就不会在文章里面继续写了,比较基础。而且读者也可以选择自己喜欢的样式去实现。
https://github.com/TeacherXin/XinBuilder2
commit: 第一节:左侧组件列表样式优化