由于Vue3文档缺失,示例10也是也跑不起来,这边参考示例改动了一下。
改动的点主要是
this
指向、$children
相关的问题
在Vue3中移除了$children
可以使用$ref
替代
参考文章:计算坐标方法重写、文档示例
关键点:计算中的子组件取值使用ref绑定即可
对于循环的Dom树可以参考模板引用
完整代码:
<template>
<div class="user-canvas" @dragenter.prevent @dragover.prevent>
<div id="content" class="w-full pb-16">
<grid-layout
class="min-h-screen"
ref="gridlayout"
:layout.sync="gridConfig.layout"
:col-num="60"
:row-height="30"
:vertical-compact="false"
:use-css-transforms="true"
>
<grid-item
ref="gridItemRefs"
v-for="item in gridConfig.layout"
class="h-full select-none relative overflow-hidden"
:static="item.static"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:minW="8"
:minH="2"
>
<div>{{item.key}}</div>
</grid-item>
</grid-layout>
</div>
</div>
</template>
import { ref, onUnmounted } from 'vue'
// ref
const gridlayout = ref(null)
const gridItemRefs = ref([])
// 计算坐标用
let mouseXY = { x: null, y: null }
let DragPos = { x: null, y: null, w: 4, h: 4, i: null }
const gridConfig ={layout:[{x: 0,y: 3,w: 4,h: 12,i: '1',static: true,moved: false}
]}
const handleDrop = (event) => {
event.preventDefault()
// TODO
}
// 开始拖动
const drag = (e) => {
let parentRect = document.getElementById('content').getBoundingClientRect()
let mouseInGrid = false
if (
mouseXY.x > parentRect.left &&
mouseXY.x < parentRect.right &&
mouseXY.y > parentRect.top &&
mouseXY.y < parentRect.bottom
) {
mouseInGrid = true
}
if (mouseInGrid === true && gridConfig.layout.findIndex((item) => item.i === 'drop') === -1) {
gridConfig.layout.push({
x: (gridConfig.layout.length * 2) % 12,
y: gridConfig.layout.length + 12, // puts it at the bottom
w: gridConfig.dragType?.w || 4,
h: gridConfig.dragType?.h || 4,
i: 'drop'
})
}
let index = gridConfig.layout.findIndex((item) => item.i === 'drop')
if (index !== -1) {
try {
gridItemRefs.value[gridConfig.layout.length - 1].$refs.item.style.display = 'none'
} catch {}
let el = gridItemRefs.value[index]
// el.dragging = { top: mouseXY.y - parentRect.top, left: mouseXY.x - parentRect.left }
let new_pos = calcXY(el, mouseXY.y - parentRect.top, mouseXY.x - parentRect.left, 1, 1)
if (mouseInGrid === true) {
// 红色游标部分
gridlayout.value.dragEvent(
'dragstart',
'drop',
new_pos.x,
new_pos.y,
gridConfig.dragType?.h || 4,
gridConfig.dragType?.w || 4
)
DragPos.i = String(index)
DragPos.x = gridConfig.layout[index].x
DragPos.y = gridConfig.layout[index].y
}
if (mouseInGrid === false) {
gridlayout.value.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, 1, 1)
gridConfig.layout = gridConfig.layout.filter((obj) => obj.i !== 'drop')
}
}
}
// 释放拖动
const dragend = (e) => {
let parentRect = document.getElementById('content').getBoundingClientRect()
let mouseInGrid = false
if (
mouseXY.x > parentRect.left &&
mouseXY.x < parentRect.right &&
mouseXY.y > parentRect.top &&
mouseXY.y < parentRect.bottom
) {
mouseInGrid = true
}
if (mouseInGrid === true) {
gridlayout.value.dragEvent('dragend', 'drop', DragPos.x, DragPos.y, 1, 1)
gridConfig.addGridItem(DragPos)
gridConfig.layout = gridConfig.layout.filter((obj) => obj.i !== 'drop')
}
gridItemRefs.value[gridConfig.layout.length - 1].$refs.item.style.display = 'none'
}
// 计算坐标
const calcXY = (el, top, left, width, height) => {
const colWidth = el.calcColWidth()
let x = Math.round((left - 10) / (colWidth + 10))
let y = Math.round((top - 10) / (el.rowHeight + 10))
const _width = width || el.innerW
const _height = height || el.innerH
x = Math.max(Math.min(x, el.cols - _width), 0)
y = Math.max(Math.min(y, el.maxRows - _height), 0)
return { x, y }
}
// 加载完成后监听鼠标事件
onMounted(() => {
document.addEventListener(
'dragover',
function (e) {
mouseXY.x = e.clientX
mouseXY.y = e.clientY
},
false
)
})
// 销毁时关闭监听
onUnmounted(() => {
document.removeEventListener(
'dragover',
function (e) {
mouseXY.x = null
mouseXY.y = null
},
false
)
})