现在的需求: 用户拖动文件到聊天框时出现黑色半透明背景,在黑色背景中拖动时黑色背景不消失,拖出黑色背景时消失

遇到的问题:enter和leave会循环触发,导致出现闪烁的情况(黑色背景出现 然后消失 一直循环)

拖曳上传文件主要依赖于三个API:  dragenterdragoverdragleave

先看一下网上关于这三个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>

这样就好啦!!!!!!!!!!!!!!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐