@[TOC](Table of Contents)
Introduction#
In the process of front-end work, it is inevitable to encounter various technologies, and drag and drop is one of them. Most of the basic knowledge and demos about drag and drop are written in detail in MDN, so I won't go into details here. I would like to share a MDN flight ticket with you.
Application Scenarios#
Everyone will encounter different scenarios and requirements, but they are all based on these events and APIs, so I will directly share a few valuable points that can save you time.
⭐ Drag and Drop to Change Element Position#
This feature relies on several events:
- dragstart
- dragover // The dragover event must cancel the default behavior of the browser in this event, otherwise the drop event will not take effect
- drop
// Step 1: Record the offset of the mouse pointer on the element
const rightItemDragStart = (event: any) => {
// Record the initial mouse offset
mouseOffsetMap.value = { x: event.offsetX, y: event.offsetY }
// Pass the ID of the dragged element
event.dataTransfer.setData('text/plain', event.target.id)
event.dataTransfer.setData('rightDrag', true)
}
// Step 2: Prevent default behavior
const handleDragOver = (event: DragEvent) => {
// Prevent default behavior to allow dropping
event.preventDefault()
}
// Step 3: Calculate and assign the element position
const handleDrop = (event: any) => {
// eventPos is the accurate position of the element after it is dropped
eventPos = {
x: event.offsetX - mouseOffsetMap.value.x,
y: event.offsetY - mouseOffsetMap.value.y,
}
...
// Prevent default behavior (opens as a link for certain elements)
event.preventDefault()
}
⭐ Drag and Drop to Change the Style of the Target Area#
This requires binding two events to the target DOM:
- dragenter
- dragleave
/**
* Handle the dragenter event
*
* @param event The drag event object
*/
const handleDragEnter = (event: any) => {
rightWrapRef.value?.classList.add('out-line')
}
/**
* Triggered when the dragged element leaves the target area
*
* @param event The drag event object
*/
const handleDragLeave = (event: DragEvent) => {
rightWrapRef.value?.classList.remove('out-line')
}
⭐ Elegant Solution for Dragleave Event Penetrating Child Elements#
If the DOM structure of the target area is complex, such as in the scenario I encountered at work:
I want to drag from the right side to the list on the left side, and when entering the left area, add a dashed border to the area, and remove it when the mouse leaves. However, a problem arises at this time. After I drag into the area, each child element's area will cause me to trigger enter and leave repeatedly, causing the dashed border to flicker. After some research, I found that this is indeed a problem, it is not event bubbling or default behavior, but the characteristics of this method. So everyone has to find another way. There are many ways to do it, but I think the most elegant one is the following. It mainly uses two methods:
- handleLeftDragEnter
- handleLeftDragLeave
const draggingCounter = ref(0)
const handleLeftDragEnter = (event: any) => {
draggingCounter.value++
// Do not process if the left element is placed in the left area
leftWrapRef.value?.classList.add('out-line')
}
const handleLeftDragLeave = (event: any) => {
draggingCounter.value--
if(draggingCounter.value === 0) {
leftWrapRef.value?.classList.remove('out-line')
}
}
Here, we use a counter variable. You can understand the logic of dragging once by looking at the printout:
Entering the element twice is because entering the outermost area counts as one, and passing through each child element also counts as one. Leaving the child element is the same. It is reasonable to judge that leaving the parent element's area when the value is 0. If you have any suggestions or opinions, please feel free to discuss and learn.
Conclusion#
📚 Vue Column
☃️ Personal Profile: A person who loves technology.
🌞 Inspirational motto: Be down-to-earth and learn with an open mind.
❗ If the article is helpful, remember to like👍 and follow✅ with your lovely hands. I will reply and return the favor as soon as possible. Welcome to further discussion.