可视化搭建项目总结(1)
简介
基于vue3搭建的低代码平台,采用图形拖拽的方式,通过拖拽物料区的组件生成JSON,通过JSON渲染出页面。
把物料区的预览按钮拖到内容区如下所示:
组件的json描述
我们使用data来描述内容区的信息:
{
// 内容区的宽高
"container": {
"width": 1500,
"height": 1500
},
需要在内容区渲染的组件信息
"blocks": [{
"top": 100,
"left": 100,
"zIndex": 1,
"key": "text",
"props": {
"text": "this is text1",
"color": "red",
"size": "14px"
}
},
{
"top": 200,
"left": 200,
"zIndex": 1,
"text": "this is text2",
"key": "input",
"model": {
"default": "username"
}
},
{
"top": 300,
"left": 300,
"zIndex": 1,
"text": "this is text3",
"key": "button",
"props": {
"text": "初始按钮",
"type": "success",
"size": "default"
}
}
]
}
组件注册
一个组件要在页面中实现,需要包括如下这些基本属性
{
label:'文本', //物料区组件的位于左上角的说明
preview: '预览文本', // 用于物料区的组件的渲染
render:() => <span>渲染文本</span>, // 用于把物料区拖拽到内容区后组件的渲染
key: 'text' // 用于json中描述组件的key对应
}
定义一个函数,返回一个对象,该对象包含一个注册函数,如下所示:
function createEditorConfig() {
let editorConfigList = []; //存放注册的组件
let editorConfigMap = new Map(); // 组件key和component的映射,
return {
editorConfigList,
editorConfigMap.
// 暴露一个注册函数
register(component) {
editorConfigList.push(component);
editorConfigMap.set(component.key, component);
}
}
}
通过调用createEditorConfig()
得到一个返回的对象,调用该对象的register方法即可注册组件,例如要注册一个文本组件
let registerConfig = createEditorConfig();
registerConfig.register({
label: '文本',
preview: () => '预览文本',
render: () => <span>渲染文本</span>,
key: 'text',
});
注册组件后,在左侧物料区通过遍历editorConfigList
,取出每一个组件的preview
和label
属性进行渲染,即可将注册的组件展示到物料区
拖拽
默认情况下,只有图片、链接和文本是可拖动的,想让其他元素变得可以拖动,需要设置元素的draggable
属性为true,也可以直接写属性名draggable
而不写属性值。
想要把物料区的组件拖拽到内容区,物料区的组件元素如下所示:
{/* 左侧物料区 */}
<div class="editor-left">
{
config.editorConfigList.map(component => (
<div
class="editor-left-item"
draggable // 表示该元素可拖拽
ondragstart={e => dragStart(e, component)}
ondragend = {dragend}
>
<span>{component.label}</span>
<div>{component.preview()}</div>
</div>
))
}
</div>
拖动元素
在某个元素被拖动时,会(按顺序)触发以下事件
- dragstart
- drag
- dragend
在按住鼠标键不放并开始移动鼠标的那一刻,被拖动元素上会触发dragstart事件。dragstart事件触发后,只要目标还被拖动就会持续触发drag事件。当拖动停止时,会触发dragend事件。
放置目标元素
在把元素拖动到一个有效的放置目标上时,会依次触发以下事件(在放置目标元素上触发):
- dragenter
- dragover
- dragleave或drop
只要一把元素拖动到放置目标上,dragenter事件就会触发,dragenter 事件触发之后,会立即触发dragover事件,并且元素在放置目标范围内被拖动会一直触发此事件。当元素被拖动到放置目标之外,dragover事件停止触发,dragleave 事件触发。如果被拖动元素被放到了目标上,则会触发 drop 事件而不是 dragleave 事件
传输数据
event
对象上暴露了一个dataTransfer
对象,用于从被拖动元素向放置目标传递字符串数据,dataTransfer对象除了用于数据传输,还可以用于确定能够对被拖动元素和放置目标执行什么操作,为此,需要使用两个属性:dropEffect
与 effectAllowed
。
本项目拖动过程中没用到传输数据的操作,只用到了dropEffect 与 effectAllowed。因此总结一下这两个属性。
dropEffect 属性可以告诉浏览器允许哪种放置行为,有4个值:
"none":被拖动元素不能放到这里。这是除文本框之外所有元素的默认值。
"move":被拖动元素应该移动到放置目标。
"copy":被拖动元素应该复制到放置目标。
"link":表示放置目标会导航到被拖动元素(仅在它是 URL 的情况下)。
为了使用 dropEffect 属性,必须在放置目标的 ondragenter 事件 处理程序中设置它。
设置dropEffect属性的同时还要设置effectAllowed。effectAllowed 属性表示对 被拖动元素是否允许 dropEffect。
"none":被拖动元素上没有允许的操作。
"copy":只允许"copy"这种 dropEffect。
"link":只允许"link"这种 dropEffect。
"move":只允许"move"这种 dropEffect。
"all":允许所有 dropEffect。
这里列出的只是一些常用的属性。
必须在dragstart
事件处理程序中设置这个属性。
物料区元素拖拽到内容区的思路
在拖拽到放置目标元素上松手时,会触发放置目标元素的ondrop事件,在ondrop事件中,给data中的blocks数组添加一个block组件对象来描述该组件如何渲染。
这里的关键在于block组件的位置信息,如果只是给top和left属性设置了e.offsetY和e.offsetX值,那么在放置目标元素的一瞬间,组件的左上角对应的是鼠标的位置,为了实现组件放置的时候,组件中间直接对应着鼠标的位置
如图所示:
黑点代表鼠标,即我们要把实线框移动到虚线框
的位置,这时候虚线框左上角的位置的计算如下
left = e.offsetX - offsetWidth / 2; //鼠标X轴位置减去元素的宽度的一半
top = e.offsetY - offsetHeight / 2; //鼠标Y轴位置减去元素的宽度的一半
但是组件的宽高如何获取呢?在没挂载组件之前,获取不到组件的宽高,因此需要在组件onMounted的钩子函数中获取组件的宽高,然后重新设置组件的left和top信息。
转载自:https://juejin.cn/post/7205527600701341757