【问题标题】:Javascript - Double File Dragover Event FiringJavascript - 双文件 Dragover 事件触发
【发布时间】:2013-01-18 04:16:28
【问题描述】:

我正在尝试创建文件拖放处理程序(将文件拖到浏览器窗口中,用于上传)。

由于某种原因,当我将拖放侦听器绑定到 $("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"));
        }
    }); 

测试:将文件拖入橙色区域,您将看到该事件连续触发多次。

【问题讨论】:

  • 不理解你的例子,但可能你应该使用 .stopPropagation() 来停止事件泡沫。这有时是多事件处理的原因..
  • api.jquery.com/event.preventDefault preventDefault 是 jquery 的 .stopPropagation() 方式。
  • preventDefault 正在阻止事件的默认行为(如果您单击链接,preventDefault 会避免跟随该链接)。停止传播停止事件冒泡。有2个不同的东西。如果在你写的api页面中搜索“传播”这个词,你什么都找不到。。
  • 什么都不应该发生(在这个脚本中),只需处理拖动动作的输入/输出。当拖动到主体上方时,我想使屏幕变暗并显示一条消息,并在他们放下文件或离开屏幕时隐藏它。
  • 我相信你对冒泡是正确的。我要试试。

标签: javascript jquery drag-and-drop


【解决方案1】:

匿名是(大部分)正确的。简而言之:当鼠标移动到放置目标内元素的 边缘 上时,您会得到一个 dropenter 对应于光标下的元素 和一个 @987654322 @ 表示先前位于光标下的元素。绝对任何后代都会发生这种情况。

您无法检查与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);
});

诀窍依赖于两个事实:

  • 当您将鼠标从孙子元素移动到子元素时,dragenterdragleave 都将排队等待目标元素 -按此顺序
  • dragenterdragleave 一起排队

这就是发生的事情。

  • dragenter 事件中,我设置了一些共享变量来指示拖动运动尚未完成解决。
  • 我使用延迟为零的setTimeout 立即将该变量改回来。
  • 但是!因为这两个事件在同一时间排队,所以在 两个 事件完成解析之前,浏览器不会运行任何预定的功能。所以接下来发生的事情是dragleave 的事件处理程序。
  • 如果dragleave 发现它与同一目标元素上的dragenter 配对,则意味着鼠标必须从某个后代移动到另一个后代。否则,鼠标实际上正在离开目标元素。
  • 然后setTimeout 最终在零秒后解析,在另一个事件发生之前设置回变量。

我想不出更简单的方法。

【讨论】:

  • 谢谢!你为我节省了很多时间! +1
【解决方案2】:

您正在为dragoverdragleavedropBODY HTMLElement 上添加一个侦听器。

当您继续在 DIV 上拖动时,会触发 dragleave,因为鼠标不再拖动到 BODY 上,而是在 DIV 上。

其次,由于您没有停止 DIV 上的气泡事件(未设置侦听器),因此在 DIV 上触发的拖拽正在冒泡到 BODY

如果我继续:

鼠标进入正文(在拖动中)

--> 火力拖过(身体)

鼠标进入body中的DIV

--> (身体的)火拖离开

--> (DIV)火力拖拽 --> 事件冒泡 --> (BODY)火力拖拽

mouseovermouseout 也有类似的问题,通过使用 mouseentermouseleave 修复。

也许您可以使用dragenter 事件类型尝试相同的代码。如果它不起作用,您可以检查event.target 是否为BODY。此测试有助于跳过不希望的拖动事件。

祝你好运

【讨论】:

  • 你搞错了; mouseentermouseleave 是以相同方式破坏的事件,mouseover + mouseout 是按您预期工作的事件。唉,没有dragout 事件。
【解决方案3】:
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;
    }
}); 

【讨论】:

    【解决方案4】:

    或者你可以使用stop(); 来停止动画生成

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-31
      • 2012-09-28
      • 1970-01-01
      相关资源
      最近更新 更多