Javascript-双文件Dragover事件触发
我正在尝试创建一个文件拖放处理程序(将一个文件拖到浏览器窗口中,用于上载) 出于某种原因,当我将拖放侦听器绑定到Javascript-双文件Dragover事件触发,javascript,jquery,drag-and-drop,Javascript,Jquery,Drag And Drop,我正在尝试创建一个文件拖放处理程序(将一个文件拖到浏览器窗口中,用于上载) 出于某种原因,当我将拖放侦听器绑定到$(“body”)而不是绑定到body中的$(“div”)时,事件会连续触发几次,有时甚至是不间断的(看似循环)。这可能是什么原因造成的 下面是代码的精简版本: var over=false; $(“正文”) .开启(“dragover”,功能(e){ e、 预防默认值(); 如果(!结束){ 过度=正确; $(“ul”)。追加($(“”)。文本(“dragover”); } }) .
$(“body”)
而不是绑定到body中的$(“div”)
时,事件会连续触发几次,有时甚至是不间断的(看似循环)。这可能是什么原因造成的
下面是代码的精简版本:
var over=false;
$(“正文”)
.开启(“dragover”,功能(e){
e、 预防默认值();
如果(!结束){
过度=正确;
$(“ul”)。追加($(“”)。文本(“dragover”);
}
})
.on(“dragleave”,函数(e){
e、 预防默认值();
如果(超过){
过度=错误;
$(“ul”).append($(“”).text(“dragleave”);
}
})
.打开(“放下”,功能(e){
e、 预防默认值();
如果(超过){
过度=错误;
$(“ul”).append($(“”).text(“drop”);
}
});
要进行测试:将文件拖到橙色区域,您将看到事件连续多次触发。您正在
主体HTMLElement上为dragover
、dragleave
和drop添加侦听器
当您继续在DIV上拖动时,会触发一个dragleave
,因为鼠标不再在主体上拖动,而是在DIV上拖动
其次,由于您没有停止DIV
上的冒泡事件(未设置侦听器),因此在DIV
上触发的dragover正在向主体发出嘟嘟声
如果我恢复发言:
鼠标进入身体(在dragover中)
-->火焰拖过(车身)
鼠标进入主体中的DIV
-->火拖离(身体)
-->火力拖过(部队)-->轰鸣事件-->火力拖过(身体)
mouseover
和mouseout
也存在类似的问题,可通过使用mouseenter
和mouseleave
解决
可能您可以使用dragenter
事件类型尝试相同的代码。如果它不起作用,您可以检查事件.target
是否是主体
。此测试有助于跳过意外的拖动事件
祝你好运这个名字(大部分)是正确的。简单地说:当鼠标移动到放置目标内某个元素的边缘上时,光标下的元素将获得一个dropenter
,之前光标下的元素将获得一个dropleave
。这绝对适用于任何后代
您无法检查与dragleave
关联的元素,因为如果将鼠标从拖放目标移动到子元素上,您将得到子元素的dropenter
,然后是目标元素的dropleave
!这有点荒谬,我不认为这是一个多么有用的设计
这是我不久前提出的一个糟糕的基于jQuery的解决方案
var $drop_target = $(document.body);
var within_enter = false;
$drop_target.bind('dragenter', function(evt) {
// Default behavior is to deny a drop, so this will allow it
evt.preventDefault();
within_enter = true;
setTimeout(function() { within_enter = false; }, 0);
// This is the part that makes the drop area light up
$(this).addClass('js-dropzone');
});
$drop_target.bind('dragover', function(evt) {
// Same as above
evt.preventDefault();
});
$drop_target.bind('dragleave', function(evt) {
if (! within_enter) {
// And this makes it un-light-up :)
$(this).removeClass('js-dropzone');
}
within_enter = false;
});
// Handle the actual drop effect
$drop_target.bind('drop', function(evt) {
// Be sure to reset your state down here
$(this).removeClass('js-dropzone');
within_enter = false;
evt.preventDefault();
do_whatever(evt.originalEvent.dataTransfer.files);
});
关键在于两个事实:
- 当您将鼠标从孙辈移动到子代时,
dragenter
和dragleave
将按该顺序排队等待目标元素
dragenter
和dragleave
一起排队
下面是发生的情况
- 在
dragenter
事件中,我设置了一些共享变量,以指示拖动运动尚未完成解析
- 我使用延迟为零的
setTimeout
立即将该变量更改回原来的值
- 但是!因为这两个事件在同一时间排队,所以在两个事件都完成解析之前,浏览器不会运行任何计划的函数。所以接下来发生的事情是
dragleave
的事件处理程序
- 如果
dragleave
看到它与同一目标元素上的dragenter
配对,这意味着鼠标必须从某个后代移动到另一个后代。否则,鼠标实际上将离开目标元素
- 然后,
setTimeout
最终在零秒后解析,在另一个事件发生之前将变量设置回原位
我想不出一个更简单的方法。var over=false;
var over = false;
$("body")
.on("dragover", function(e){
e.preventDefault();
if (! over) {
over = true;
$("ul").append($("<li/>").text("dragover"));
}
})
.on("dragleave", function(e){
e.preventDefault();
if (over) {
over = false;
$("ul").append($("<li/>").text("dragleave"));
}
})
.on("drop", function(e){
e.preventDefault();
if (over) {
over = false;
}
});
$(“正文”)
.开启(“dragover”,功能(e){
e、 预防默认值();
如果(!结束){
过度=正确;
$(“ul”)。追加($(“”)。文本(“dragover”);
}
})
.on(“dragleave”,函数(e){
e、 预防默认值();
如果(超过){
过度=错误;
$(“ul”).append($(“”).text(“dragleave”);
}
})
.打开(“放下”,功能(e){
e、 预防默认值();
如果(超过){
过度=错误;
}
});
或者您可以使用stop()
停止动画构建不理解您的示例,但可能您应该使用.stopPropagation()停止事件buble。这有时是多事件治疗的原因。。preventDefault是jquery的操作方式。stopPropagation()。preventDefault是防止事件的默认行为(如果单击链接,请使用preventDefault避免跟随链接)。停止传播停止事件的嗡嗡声。有两种不同的东西。如果您在编写的api页面中搜索“传播”一词,您将找不到任何内容。在这个脚本中,不应该发生任何事情,只需处理拖入/拖出操作。当拖到身体上方时,我想调暗屏幕并显示消息,当他们放下文件或离开屏幕时隐藏消息。不过,我相信你关于冒泡的说法是正确的。我要试试,你倒过来了mouseenter
和mouseleave
是以相同方式中断的事件,而mouseover
+mouseout
则是您可能期望的工作方式。唉,没有dragout
var over = false;
$("body")
.on("dragover", function(e){
e.preventDefault();
if (! over) {
over = true;
$("ul").append($("<li/>").text("dragover"));
}
})
.on("dragleave", function(e){
e.preventDefault();
if (over) {
over = false;
$("ul").append($("<li/>").text("dragleave"));
}
})
.on("drop", function(e){
e.preventDefault();
if (over) {
over = false;
}
});