我正在尝试创建一个文件拖放处理程序(将一个文件拖到浏览器窗口中,用于上传)。
由于某些原因,当我将拖放侦听器绑定到$("body")而不是主体中的$("div")时,事件会连续触发几次,有时甚至不会停止(似乎是循环)。这可能是什么原因造成的?
下面是代码的精简版本:http://jsfiddle.net/WxMwK/9/
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;
$("ul").append($("<li/>").text("drop"));
}
}); 测试:将一个文件拖到橙色区域,您将看到该事件连续多次触发。
发布于 2013-01-18 13:13:51
无名氏(大部分)是正确的。简单地说:当鼠标移动到拖放目标中元素的边缘时,您将获得光标下元素的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配对,这意味着鼠标一定是从某个后代移动到了另一个后代。否则,鼠标实际上离开了目标element.setTimeout最终在几秒钟后解析为零,在另一个事件出现之前将该变量重新设置为零。我想不出更简单的方法了。
发布于 2013-01-18 13:00:57
您正在为dragover、dragleave和drop在BODY HTMLElement上添加侦听程序。
当您继续在DIV上拖动时,会触发一个dragleave,因为鼠标不再在身体上拖动,而是在DIV上拖动。
其次,由于您没有停止DIV上的气泡事件(未设置侦听器),因此在DIV上触发的拖拽将阻塞到BODY。
如果我继续:
鼠标进入身体(处于拖拽状态)
--> fire在(body)上拖动
鼠标进入身体中的DIV
--> fire拖动离开(主体)
--> fire drag over (of DIV) --> event bubling --> fire drag over (of BODY)
mouseover和mouseout也存在类似的问题,可以使用mouseenter和mouseleave修复。
也许您可以使用dragenter事件类型尝试相同的代码。如果它不工作,你可以检查event.target是否是BODY。此测试有助于跳过不需要的拖动事件。
祝好运
发布于 2013-11-12 04:53:26
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;
}
}); https://stackoverflow.com/questions/14392293
复制相似问题