JavaScript dragleave仅首次触发问题排查求助
这个问题我之前做拖拽上传功能时也踩过坑!核心问题主要出在drop操作后计数器状态没有重置,再加上dragenter/dragleave在嵌套元素上的触发逻辑容易搞乱计数器,给你几个靠谱的解决思路和修正后的代码:
1. 必须在drop事件后重置计数器
当你完成drop操作后,当前的counter值很可能不是0(比如拖拽过程中经过了子元素,导致counter累加后没减到0),这会导致后续的dragleave判断永远不满足counter === 0,modal就一直不会隐藏。所以一定要在drop事件里强制重置计数器并隐藏弹窗。
2. 避免子元素触发dragenter/dragleave干扰计数器
拖拽时如果目标元素内部有子元素,鼠标经过子元素时也会触发dragenter(进入子元素)和dragleave(离开父元素到子元素),这会让counter的数值完全混乱。我们可以通过判断事件的currentTarget和target是否一致,确保只有当鼠标真正进入/离开目标元素本身时才修改计数器。
3. 补充dragover事件(关键!)
很多浏览器要求必须阻止dragover的默认行为,才能正常触发drop事件,这一步很容易漏掉。
修正后的完整代码
var counter = 0; // 用on()代替bind(),jQuery 3.0+推荐使用on() $('.bodierClass').on({ dragenter: function(ev) { ev.preventDefault(); ev.stopPropagation(); // 只在鼠标真正进入目标元素本身时计数 if (ev.currentTarget === ev.target) { counter++; $('#filedrag').modal('show'); } }, dragleave: function(ev) { ev.preventDefault(); ev.stopPropagation(); // 只在鼠标真正离开目标元素本身时减计数 if (ev.currentTarget === ev.target) { counter--; if (counter === 0) { $('#filedrag').modal('hide'); } } }, dragover: function(ev) { // 阻止默认行为才能触发drop ev.preventDefault(); ev.stopPropagation(); }, drop: function(ev) { ev.preventDefault(); ev.stopPropagation(); // 强制重置计数器,确保后续拖拽状态正确 counter = 0; $('#filedrag').modal('hide'); // 这里添加你的文件处理逻辑,比如读取上传文件 // var files = ev.originalEvent.dataTransfer.files; } });
额外提示
如果你的.bodierClass内部有很多复杂子元素,用ev.currentTarget === ev.target可能还是会有判断偏差,这时候可以改用下面的判断逻辑,确保目标元素及其子元素的dragenter事件被统一处理:
// 在dragenter和dragleave里替换判断条件 if ($(ev.target).closest('.bodierClass')[0] === ev.currentTarget) { // 你的计数逻辑 }
内容的提问来源于stack exchange,提问作者Marat
相关产品推荐
相关产品推荐

