HTML5拖放事件不起作用,除非处理dragover事件。

43

我正在监听drop事件并执行e.preventDefault(),但它仍然试图打开被拖动的文件。这个功能昨天还能正常工作,但今天突然就失效了。我创建了一个JsFiddle#bwquR/10来演示同样的问题。

编辑:

看起来如果不处理dragover事件,就无法处理drop事件。即使在这个 fiddle 中,如果你注释掉dragover,它仍然不会工作。
在实际工作中,我错拼了dragover的单词,但问题仍然是:drop没有dragover就不能工作。

事实上,这个 fiddle 实际上是能够工作的,但是因为 body 很小(只有文本 DROP),所以它只在包含文本“DROP”的小区域中触发drop事件,而不是整个 body。 所以我认为它没有工作。对于造成的困惑,非常抱歉。


2
刚遇到了这个问题,你的问题帮助我解决了它。我在dragover事件中返回了false,然后拖放开始工作了。谢谢! - Fydo
1
有时候定义一些 CSS 样式 body { width:300px; height: 300px; border: 1px solid #f1f1f1; } 会很有帮助,这样你就可以看到放置区域的实际大小。顺便说一下,这是一个不错的示例。 - iiminov
4个回答

50

我猜这是因为如果没有dragOver事件处理程序,那么将使用dragOver事件的默认事件处理程序,因此在此之后不会触发任何drop事件。在drop事件之前需要使用e.preventDefault来处理dragOver事件。


10
哦,这个系统设计太糟糕了。谢谢提供信息! - cronoklee
1
@cronoklee 四年过去了,我仍然持有同样的观点。设计不好,很棘手。 - Thanasis

8
如果您想允许拖放,请通过取消事件来阻止默认处理。您可以通过从属性定义的事件侦听器返回false或调用事件的event.preventDefault方法来实现此操作。后者可能更可行,因为它在单独脚本中定义的函数中使用。具体信息请参见:https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/Drag_operations
<div ondragover="return false">
<div ondragover="event.preventDefault()">

在dragenter和dragover事件中调用preventDefault方法将表明该位置允许放置。然而,通常只有在某些情况下才希望调用preventDefault方法,例如仅当拖动链接时才调用。为此,请调用一个检查条件并仅在满足条件时取消事件的函数。如果条件不满足,则不要取消事件,如果用户释放鼠标按钮,则不会发生放置。
参考链接:https://developer.mozilla.org/en-US/docs/Web/Events/dragover
  /* events fired on the drop targets */
  document.addEventListener("dragover", function( event ) {
      // prevent default to allow drop
      event.preventDefault();
  }, false);

2
感谢您提供这么详细的答案。还有一个段落您没有引用,但我认为它非常重要,可以解释为什么要这样做:“使用dragenter和dragover事件的侦听器来指示有效的放置目标,也就是拖动项目可以放置的位置。大多数网页或应用程序的区域都不是有效的数据放置位置。因此,默认处理这些事件的方式是不允许放置。” - RayLuo

4

我不确定是否正确理解了你的问题,但如果你想读取拖放的文件,你需要处理dragover事件,并至少添加以下代码:

evt.dataTransfer.dropEffect = 'copy';

否则,dropEffect 默认为 null,您将无法获取任何数据。

2
这就是阻止我进入“drop()”事件的罪魁祸首。但是,我不得不使用“evt.originalEvent.dataTransfer.dropEffect =“copy”;”来防止在我将文件保持在拖放区域上时出现“Uncaught TypeError: Cannot set property 'dropEffect' of undefined”。 - iiminov
1
@iiminov 你不得不那样做是因为你正在使用jQuery。jQuery 创建了一个自定义事件对象并将原始事件对象保存在 originalEvent 属性下。 - Lucio Paiva

1

对我来说运行良好。您是将其作为HTTP还是FILE URL加载的?我认为在Chrome中它需要是一个HTTP URL。


作为HTTP本地主机,它昨天还能正常工作。我不明白发生了什么事。 - Neel Basu
JsFiddle在Chrome中对我来说正常工作。一旦文件悬停在DROP上,我就会收到DragOver消息。当我注释掉那个警报时,我可以将其拖放并获得Dropped消息。 - Maurice
1
它对我也起作用。但只在写有“DROP”的区域内有效,而不是整个主体。所以我以为它没有起作用。抱歉。不过我已经编辑了我的问题。抱歉。 - Neel Basu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接