好家伙,
0.代码已开源
Fattiger4399/lowcode-demo: 一个简单的低代码编辑器 技术栈:Vue3 element-plus jsx (github.com)
该章实现的效果:组件从物料区到画布的拖拽
1.分析
先来分析,鼠标点击物料区的某个组件,再将其拖拽到画布这个过程
我们如何实现组件的拖拽??
- 鼠标按下组件时获取当前选中组件的信息
- 绑定鼠标的移动和松开事件,松开时在画布上渲染当前块。
- 将拖拽的组件渲染在画布上。
<div> <div class="editor-left"> {/* 根据注册列表 渲染对应的内容 可以实现h5的拖拽*/} {config.componentList.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> <div class="editor-top">菜单栏</div> <div class="editor-right">属性控制栏目</div> <div class="editor-container"> <div class="editor-container-canvas"> {/* 产生内容 */} <div class="editor-container-canvas__content" style={containerStyles.value} ref={containerRef} onm ousedown={containerMousedown}> { (data.value.blocks.map(block => ( <EditorBlock class={block.focus ? 'editor-block-focus' : ''} block={block} onm ousedown={(e) => blockMousedown(e, block)} ></EditorBlock> ))) } </div> </div> </div> </div>
2.处理物料区
import { registerConfig as config } from './utils/editor-config'
config为我们的组件注册表信息
const { dragstart, dragend } = useMenuDragger(containerRef, data)
{config.componentList.map(component => ( <div class="editor-left-item" draggable onDragstart={e => dragstart(e, component)} onDragend={dragend} > <span>{component.label}</span> <div>{component.preview()}</div> </div> ))}
此处为物料组件添加onDragstart和onDragend事件
useMenuDragger.js
export function useMenuDragger(containerRef,data){ let currentComponent = null; const dragenter = (e) => { e.dataTransfer.dropEffect = 'move'; //h5的拖动图标 } const dragover = (e) => { e.preventDefault(); } const dragleave = (e) => { e.dataTransfer.dropEffect = 'none'; } const drop = (e) => { //先留在这 console.log(e.offsetY) console.log(e.offsetX) let blocks = data.value.blocks;//内部已渲染的组件 data.value = { ...data.value, blocks: [ ...blocks, { top: e.offsetY, left: e.offsetX, zIndex: 1, key: currentComponent.key, alignCenter: true //松手时剧中 } ] } currentComponent = null } const dragstart = (e, component) => { //dragenter进入元素中 containerRef.value.addEventListener('dragenter', dragenter) containerRef.value.addEventListener('dragover', dragover) containerRef.value.addEventListener('dragleave', dragleave) containerRef.value.addEventListener('drop', drop) currentComponent = component } const dragend = (e) => { containerRef.value.removeEventListener('dragenter', dragenter) containerRef.value.removeEventListener('dragover', dragover) containerRef.value.removeEventListener('dragleave', dragleave) containerRef.value.removeEventListener('drop', drop) } return{ dragstart, dragend } }
3.处理画布区域
<div class="editor-container-canvas__content" style={containerStyles.value} ref={containerRef} onm ousedown={containerMousedown}> { (data.value.blocks.map(block => ( <EditorBlock class={block.focus ? 'editor-block-focus' : ''} block={block} onm ousedown={(e) => blockMousedown(e, block)} ></EditorBlock> ))) } </div>
组件传值
当组件被拉倒画布后
const drop = (e) => { //先留在这 console.log(e.offsetY) console.log(e.offsetX) let blocks = data.value.blocks;//内部已渲染的组件 data.value = { ...data.value, blocks: [ ...blocks, { top: e.offsetY, left: e.offsetX, zIndex: 1, key: currentComponent.key, alignCenter: true //松手时剧中 } ] } currentComponent = null }
将新组件(拖拽组件)的相关值添加到data.value.blocks中,最后由渲染器进行渲染
(data.value.blocks.map(block => ( <EditorBlock class={block.focus ? 'editor-block-focus' : ''} block={block} onm ousedown={(e) => blockMousedown(e, block)} ></EditorBlock> )))
标签:blocks,低开,component,value,编辑器,组件,containerRef,data,拖拽 From: https://www.cnblogs.com/FatTiger4399/p/17847361.html