目录

大体介绍

主要思路

设置计算属性,实现与data.json中数据的双向绑定

设置计算属性,实现画布大小数据的绑定

给预览区绑定一个ref,用于绑定事件

实现组件区菜单拖拽功能

在editor.jsx中使用useMenuDragger.js方法

大致实现结果

大体介绍

我们要实现在组件区点击选中一个想要的组件,并拖动到预览区来进行渲染,松开鼠标就可以完成组件的位置的确定和渲染。

主要思路

首先我们在主页面中引入data.json中的数据,用于对data.json中的数据进行增删改查。然后我们可以给产生画布的div添加一个style属性,用于对画布的宽和高来进行渲染。再然后我们可以给产生画布的div添加一个{ref}表示,用于监听鼠标的点击和移动事件。最后我们再写一个js文件,传入data和ref数据,对鼠标事件进行监听和对div中画布进行渲染操作。

设置计算属性,实现与data.json中数据的双向绑定

在editor.jsx文件中

// 设置计算属性,以便于实现数据的双向绑定
        const data = computed({
            get() {
                return props.modelValue
            },
            set(newValue) {
                ctx.emit('update:modelValue', deepcopy(newValue))
            }
        })

设置计算属性,实现画布大小数据的绑定

在editor.jsx文件中

// 设置计算属性,用来改变和渲染画布的大小
        const containerStyles = computed(() => ({
            width: data.value.container.width + 'px',
            height: data.value.container.height + 'px',
        }))

给预览区绑定一个ref,用于绑定事件

const containerRef = ref(null)

实现组件区菜单拖拽功能

新建一个 useMenuDragger.js 文件,接收两个参数:data(JSON数据),containterRef(用于绑定事件)。

// 菜单拖拽功能
import {events} from "@/packages/events";

export function useMenuDragger(containerRef, data) {
    let currentComponent = null;
    const dragenter = (e) => {
        e.dataTransfer.dropEffect = 'move';

    }
    const dragover = (e) => {
        e.preventDefault();
    }
    const dragleave = (e) => {
        e.dataTransfer.dropEffect = 'none';
    }
    const drop = (e) => {
        // console.log(currentComponent);

        let blocks = data.value.blocks; // 内部已经渲染的组件
        data.value = {
            ...data.value, blocks: [
                ...blocks,
                {
                    top: e.offsetY,
                    left: e.offsetX,
                    zIndex: 1,
                    key: currentComponent.key,
                    alignCenter: true, // 实现松手的时候鼠标可以居中
                    focus: false    // 没有选定的状态
                }
            ]
        }
        currentComponent = null;
    }
    const dragstart = (e, component) => {
        containerRef.value.addEventListener('dragenter', dragenter)
        containerRef.value.addEventListener('dragover', dragover)
        containerRef.value.addEventListener('dragleave', dragleave)
        containerRef.value.addEventListener('drop', drop)
        currentComponent = component;
        events.emit('start');
    }
    const dragend = (e) => {
        containerRef.value.removeEventListener('dragenter', dragenter)
        containerRef.value.removeEventListener('dragover', dragover)
        containerRef.value.removeEventListener('dragleave', dragleave)
        containerRef.value.removeEventListener('drop', drop)
        events.emit('end');
    }
    return {
        dragstart,
        dragend
    }
}

在其中:

  dragenter进入元素中 添加一个移动的标识,就是在鼠标点击一个组件进行移动,移动到预览区的时候就可以触发一个移动标识。
  dragover 在目标元素经过 必须阻止默认行为 否则不能触发drop,就是在鼠标点击一个组件进行移动,在预览区进行移动的时候,一定要阻止它的默认行为。就是在鼠标点击一个组件进行移动
  dragleave 离开元素的时候 需要添加一个禁用标识,就是在鼠标点击一个组件进行移动,如果不在预览区进行移动的话,鼠标会变成一个禁用的标识,表明组件不能在这里进行放置。
  drop 松手的时候 根据拖拽的组件 添加一个组件,就是在预览区放置,会渲染出一个新的组件。

在editor.jsx中使用useMenuDragger.js方法

import {useMenuDragger} from "@/packages/useMenuDragger";


            <div class="editor-left">
                {/*根据注册列表  渲染对应的内容*/}
                {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>

大致实现结果

 

Logo

低代码爱好者的网上家园

更多推荐