Vue封装拖曳上传,解决重复触发dragenter和dragleave问题
用户拖动文件到聊天框时出现黑色半透明背景,在黑色背景中拖动时黑色背景不消失,拖出黑色背景时消失。:enter和leave会循环触发,导致出现闪烁的情况(黑色背景出现 然后消失 一直循环)进入时触发,并且只触发一次,实际上是只要拖动元素在目标元素里面就会一直触发,拖动元素在目标元素移动时触发。拖动元素进入目标元素时触发。拖动元素离开目标元素时触发。触发dragenter时,触发dragleave时,
·
现在的需求: 用户拖动文件到聊天框时出现黑色半透明背景,在黑色背景中拖动时黑色背景不消失,拖出黑色背景时消失
遇到的问题:enter和leave会循环触发,导致出现闪烁的情况(黑色背景出现 然后消失 一直循环)
拖曳上传文件主要依赖于三个API: dragenter,dragover,dragleave
先看一下网上关于这三个API的介绍是这样的:
dragenter:拖动元素进入目标元素时触发
dragover:拖动元素在目标元素移动时触发
dragleave:拖动元素离开目标元素时触发
这样介绍就是个大坑!
很容易就被误导为dragenter时进入时触发,并且只触发一次,实际上是只要拖动元素在目标元素里面就会一直触发, dragleave只在拖动元素离开时触发
然后你就会把代码写成这样
<template>
<div class="uploadContainer"
@dragover.prevent
@dragenter.prevent="handleDropEnter"
@dragleave.prevent="handleDropLeave"
@drop="handleDrop">
<slot></slot>
<div class="overlay" v-if="showOverlay">
</div>
</div>
</template>
<script lang="ts" setup>
// 导入工具库
import { ref, onMounted, onUnmounted } from 'vue'
// 导入组件库
// 定义属性
const showOverlay = ref<Boolean>(false)
// 定义方法
const handleDropEnter = (e: any)=>{ //拖曳进入目标元素
showOverlay.value = true
}
const handleDropLeave = () => { // 拖曳离开目标元素
showOverlay.value = false
}
const handleDrop = (e: any)=> {
}
// 生命周期
onMounted(() => {
})
onUnmounted(() => {
})
</script>
<style lang="less" scoped>
.uploadContainer {
height: 100%;
width: 100%;
position: relative;
&.flex {
display: flex;
}
.overlay {
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1000;
background-color: rgba(0,0,0,0.5);
}
}
解决问题的方案
触发dragenter时,显示模态框
触发dragleave时,延迟500ms隐藏模态框
触发dragover时,移除dragleave设置的延时隐藏
<template>
<div
class="uploadContainer"
@dragenter="handleDragEnter"
@dragover.prevent="handleDragOver"
@dragleave.prevent="handleDragLeave"
@drop="handleDrop"
>
<slot></slot>
<div class="overlay" v-if="isDraggingOver"></div>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
const isDraggingOver = ref<boolean>(false);
let dragLeaveTimeout: number | undefined;
const handleDragEnter = () => {
isDraggingOver.value = true;
};
const handleDragOver = (e: Event) => {
e.preventDefault();
// 保持拖拽状态为true
clearTimeout(dragLeaveTimeout as number); // 清除可能的离开定时器
};
const handleDragLeave = () => {
// 设置一个短暂的延迟,以便在用户短暂离开时不会立即隐藏遮罩层
dragLeaveTimeout = window.setTimeout(() => {
// 检查拖拽区域是否仍然处于hover状态(这通常意味着鼠标没有在上面)
// 注意:这种方法可能不是100%准确,因为它依赖于:hover伪类
// 在更复杂的布局中,可能需要更精确的方法来确定鼠标位置
isDraggingOver.value = false;
}, 100); // 延迟时间可以根据需要调整
};
const handleDrop = (e: DragEvent) => {
e.preventDefault();
clearTimeout(dragLeaveTimeout as number); // 清除离开定时器
isDraggingOver.value = false; // 通常在drop后隐藏遮罩层,但也可以根据需要保持显示
const files = e.dataTransfer.files;
console.log('Dropped files:', files);
// 处理文件上传逻辑...
};
</script>
<style lang="less" scoped>
.uploadContainer {
position: relative;
width: 100%;
height: 100%;
.overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5); /* 初始透明 */
pointer-events: none; /* 确保 overlay 不会干扰拖拽操作 */
}
}
</style>
这样就好啦!!!!!!!!!!!!!!

更多推荐


所有评论(0)