1. 背景
公司最近在做能力库,为公司的未来业务赋能,恰好需要一款低代码可视化拖拽平台。所以...
本项目技术栈是:Vue3+TypeScript+Element-plus
本篇文章将介绍平台的主要功能实现思路,详情请移步gitee,平台在线访问地址:Vue3-Visual-Editor,代码地址:gitee。
2. 长啥样,有啥功能
目录结构
├─public
└─src
├─assets 静态资源
│ ├─images
│ └─styles
├─data mock数据
├─packages
| ├─components 组件列表
│ | ├─block-resize - 拖拽改变尺寸组件
│ │ ├─dropdown - 右键下拉菜单组件
│ │ ├─import-export-dialog - 数据导入导出弹窗组件
│ │ ├─number-range - 数字范围组件
│ │ ├─table-prop-editor - 属性添加组件
│ │ ├─visual-editor-block - 画布中展示的组件
│ │ ├─visual-editor-content - 画布容器
│ │ ├─visual-editor-header - 头部操作区容器
│ │ ├─visual-editor-menu - 左侧组件列表容器
│ │ └─visual-editor-props - 右侧属性管理容器
│ ├─plugins
│ │ └─command - 注册头部操作功能
│ | ├─Command.plugin.ts - 命令注册基础函数
│ | └─VisualCommand.ts - 头部功能命令注册
│ |
│ ├─utils - 工具函数
| | └─event.ts - 发布订阅工具函数
| └─Index.tsx - 容器包裹层
├─main.ts - 入口
└─App.vue
主要功能
- 拖拽组件到画布区
- 画布组件选中态,拖拽位置及改变宽高
- 标识线贴边检测
- 撤销重做功能
- 导入导出功能
- 置顶、置底、删除、清空功能
- 功能命令快捷键,支持单选多选
- 画布中组件右键展示操作项
- 画布中组件添加属性、绑定字段
- 根据组件标识,通过作用域插槽,自定义组件行为
3. 设计理念及数据交互
基于JSON Schema
,简单易用。中心思想就是数据控制视图显示,所有的操作功能本质上都是在操作数据。
4. 功能拆解,分析实现
准备工作
- App.vue
export default defineComponent({
name: "App",
data() {
return {
// 数据中心,展示就靠它
jsonData: {
container: {
width: 1000,
height: 1000
},
blocks: []
},
// 配置数据
config: VisualConfig,
// 绑定的数据
formData: {},
// 自定义属性
customProps: {}
};
}
});
</script>
下面正式开始功能思路介绍,详细实现捋一遍代码就都知道了。
拖拽菜单组件到画布区
核心:dragable,dragstart、dragend
(用在当前拖拽组件),dragenter、dragover、dragleave、drop
(用在画布)
画布组件选中态,拖拽位置及改变宽高
标识线贴边检测
撤销重做功能
const state = reactive({
// 游标,控制执行queue中的哪一项
current: -1,
// 撤回重做的方法都存在queue中
queue: [] as CommandExecute[], // [{undo, redo}, {deleteUndo, deleteRedo}, {dragUndo, dragRedo} ...]
// 注册的命令对应的撤回重做方法都存在这里
commands: {} as Record<string, (...args: any[]) => void>, // {undo:()=>{redo()}, redo:()=>{redo()}, delete:()=> {redo()}, drag:()=> {redo()}, ...}
// 注册的完整对象集合
commandArray: [] as Command[], [{name: 'xx', keywords: "", followQueue: false, execute: () => {redo, undo}}]
// 移除事件
destroyList: [] as ((() => void | undefined))[], removeEventListener
})
// 注册函数
const register = (command: Command) => {
// 保存注册的对象
state.commandArray.push(command);
// 根据名称构建注册对象,并保存,等到调用的时候执行内部代码
state.commands[command.name] = (...args) => {
// 执行redo
const { undo, redo } = command.execute(...args);
redo();
// 如果需要保存到queue中,则进行保存,游标加1
if (command.followQueue) {
let { queue, current } = state;
if (queue.length > 0) {
queue = queue.slice(0, current + 1); // 1 => 2 => 3 => 4 => 3 => 5, 4不会保留
state.queue = queue;
}
queue.push({ undo, redo })
state.current = current + 1;
}
}
// 调用注册对象的init方法
command.init && command.init();
}
导入导出功能
置顶、置底、删除、清空功能
功能命令快捷键,支持单选多选
画布中组件右键展示操作项
画布中组件添加属性、绑定字段
根据组件标识,通过作用域插槽,自定义组件行为
<template #myBtn>
<el-button v-if="formData.food === 'dangao'">自定义按钮</el-button>
<el-tag v-else>自定义标签</el-tag>
</template>
data() {
return {
// 绑定的数据
formData: {},
// 自定义属性
customProps: {
myBtn: { // myBtn是组件标识,即slotName
onClick: () => {
this.$notify({ message: "执行动作" });
}
},
mySelect: {
onChange: (val: any) => {
this.$notify({ message: `下拉框发生变化,${val}` });
}
}
}
};
}
5. 小结
以上实现的是常用功能,还有很多优秀的功能可以添加进来,比如:
- 增加事件配置
- 拖拽框选多个组件,进行组合和拆分
- 画布中选中组件复制粘贴一份
- 插入图片
- ...
后续有时间我将继续完善相关功能,让他变的更好用更通用一些。
6. 参考资料
- resct-visual-editor
- 可视化拖拽组件库技术要点
- ref-line
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!