本文将一步一步详细记录制作一个简单的低代码编辑器框架的过程
前言
什么是低代码编辑器?
举个例子:假如你要建房子
- 传统方式(写代码): 你需要从烧砖头、锯木头开始,一点点亲手建造,需要专业的建筑知识和工具,非常耗时费力。
- 低代码方式: 就像用乐高积木或者现成的模块化房屋组件来盖房子。大部分结构、门窗、水电线路都有现成的、标准化的“积木块”,你只需要用鼠标拖一拖、拽一拽,把它们拼装起来,再稍微调整一下大小、颜色和位置就可以了。需要复杂功能的地方(比如一个特殊的智能灯光系统),才需要请专业的电工(写少量代码)来处理。
总结:
低代码编辑器就是一个图形化的“应用拼装台”。它提供大量现成的功能“积木块”和可视化工具,让你通过鼠标拖拽、连线、配置,就能像搭积木一样快速构建出软件应用,大大降低了对传统编程的依赖,让开发变得更快、更简单。
低代码编辑器长什么样?
低代码编辑器主要包含三个区域:
- 左边为组件放置区域(物料区),用于用户挑选自己需要的组件并可进行拖拽
- 中间为画布区,向用户展示组件拖拽拼接后的效果
- 右边为属性区,可以供用户修改自己选择的组件的样式和属性
主要逻辑就是:用户拖拽添加组件时,编辑器会将组件对象添加到JSON树的指定层级中。这个JSON树完整描述了整个页面的结构和组件属性。编辑器监听JSON树的变化,并通过渲染引擎将其动态转化为HTML/CSS进行可视化展示。
开始搭建低代码编辑器框架
使用的是React框架
创建项目
创建一个项目文件夹,右键打开终端输入指令npm create vite@latest ---->输入项目名称:lowcode-editor ---->选择框架:React ---->选择语言:TypeScript ---->使用编辑器打开(选择一款自己喜欢的编辑器即可) ---->npm i 安装依赖 ----> npm run dev运行项目
创建一个低代码组件的根组件
在src文件夹下创建editor文件夹---->文件夹下创建index.tsx文件(装低代码组件的)---->将该文件引入到App.tsx中
import LowcodeEditor from './editor/index.tsx'
export default function App() {
return (
<LowcodeEditor />
)
}
安装tailwindcss
原子化css,只需要写类名,不需要写css
tailwind.nodejs.cn/docs/border…
- 在项目根目录终端下运行npm install -D tailwindcss@3
- 再运行npm i autoprefixer
- 接着运行npx tailwindcss init -p
初始化tailwindcss配置文件和postcss的配置文件(postcss通常用作css的兼容问题,让浏览器能够读懂) - 在tailwind.config文件下进行配置tailwindcss能够扫描到的文件
/** @type {import('tailwindcss').Config} */
export default {
content: [//配置tailwindcss扫描的文件
'./index.html',
'./src/**/*.{js,jsx,ts,tsx}',//src文件夹下的所有文件
],
theme: {
extend: {},
},
plugins: [],
}
- 在src文件夹根部的index.css文件中添加以下代码
@tailwind base;
@tailwind components;
@tailwind utilities;
- 添加Tailwind CSS IntelliSense插件
安装allotment实现拖动改变容器大小
- 在项目根目录终端下运行npm install allotment --save
- 在editor文件夹根目录的index.tsx文件中引入allotment
import { Allotment } from "allotment";
import "allotment/dist/style.css";
- 在editor文件夹下创建一个components文件夹,再在components文件夹中分别创建头部组件Header文件夹,物料区组件Materail文件夹,画布区组件EditArea文件夹,属性区组件Setting文件夹,并分别在文件夹内创建属于自己的index.tsx文件
- 将创建的组件文件引入editor根部的index.tsx文件中
import Header from './components/Header/index.tsx'
import Setting from './components/Setting/index.tsx'
import EditArea from './components/EditArea/index.tsx'
import Materail from './components/Materail/index.tsx'
- 分别用Allotment.Pane包裹物料区,画布区,属性区,以实现区域可拖动改变大小的效果,并分别最大宽度
editor/index.tsx
export default function LowcodeEditor() {
return (
<div className="h-[100vh] flex flex-col">
<div className="h-[60px] flex items-center border-b-[1px] border-[#000]">
<Header></Header>
</div>
<Allotment>
{/* preferredSize默认大小 */}
<Allotment.Pane preferredSize={240} maxSize={500} minSize={200}>
<Materail></Materail>
</Allotment.Pane>
<Allotment.Pane>
<EditArea></EditArea>
</Allotment.Pane>
<Allotment.Pane preferredSize={300} maxSize={800} minSize={300}>
<Setting></Setting>
</Allotment.Pane>
</Allotment>
</div>
)
}
安装zustand 仓库
- 在项目根部终端输入:npm install zustand --save
- 在editor文件夹下创建stores文件夹
安装antd(可以直接引用想要的组件 如按钮)
- 在项目根部终端输入:npm install antd --save
- 因为使用的是react19版本,会有兼容问题,所以需要再输入:npm install @ant-design/v5-patch-for-react-19 --save
- 并且在在应用入口(mian.tsx文件)处引入兼容包
import '@ant-design/v5-patch-for-react-19'
编写header组件(进行简单的头部编写)
- 需要引入antd内的Space组件和Button组件,用Space包裹的组件,组件之间会自动隔开间隙
- 需创建一个useSate状态变量mode,记录预览和编辑的状态,便于后续按钮切换,当mode为edit时展示预览按钮,mode为preview时展示退出预览按钮
Header/index.tsx
import { Space } from "antd"//引入Space
import { Button } from "antd"//引入Button
import { useState } from 'react'//引入useState
export default function Header() {
const [mode, setMode] = useState('edit')//表示编辑和预览状态
return (
<div className='w-[100%] h-[100%]'>
<div className='h-[50px] flex justify-between items-center px-[20px]'>
<div>低代码编辑器</div>
<Space>
{
mode === 'edit' && (
<Button type="primary">预览</Button>
)
}{
mode === 'preview' && (
<Button type="primary">退出预览</Button>
)
}
</Space>
</div>
</div>
)
}
由于mode状态变量不止Header一个组件需要使用,所以需要创建仓库进行存储,实现组件之间状态共享
创建仓库(实现组件之间状态共享)
- 在stores文件夹下创建components.tsx文件
- 引入create方法进行仓库的创建
- 抛出仓库
stores/components.tsx
import { create } from 'zustand'//引入create方法
export const useComponentsStore = create((set) => ({
//数据
mode:'edit',
//方法
setMode:(type:any)=>set({mode:type}),//将mode都值改为传入的值
}))
export default useComponentsStore//抛出仓库
- 回到Header/index.tsx,引入仓库
- 并将仓库内的mode状态和setMode方法进行解构引入
- 两个按钮各绑定了点击事件,点击预览按钮,便会使得mode值变为preview,从而按钮变为退出预览按钮,点击退出预览按钮同理
Header/index.tsx
import { Space } from "antd"
import { Button } from "antd"
import { useState } from 'react'
import {useComponentsStore} from '../../stores/components.tsx'
export default function Header() {
// const [mode, setMode] = useState('edit')//表示编辑和预览状态
const { mode, setMode } = useComponentsStore((state: any) => state)
return (
<div className='w-[100%] h-[100%]'>
<div className='h-[50px] flex justify-between items-center px-[20px]'>
<div>低代码编辑器</div>
<Space>
{
mode === 'edit' && (
<Button type="primary" onClick={() => setMode('preview')}>预览</Button>
//调用从仓库内获取的setMode方法
)
}{
mode === 'preview' && (
<Button type="primary" onClick={() => setMode('edit')}>退出预览</Button>
)
}
</Space>
</div>
</div>
)
}
小结:
完成了主页面的头部组件,身体部分的左中右组件,并实现了拖动改变容器大小的功能,粗略编写了头部组件的简单逻辑