HTML5 dragend 事件立即触发

Posted

技术标签:

【中文标题】HTML5 dragend 事件立即触发【英文标题】:HTML5 dragend event firing immediately 【发布时间】:2013-11-07 12:44:10 【问题描述】:

我有几个可拖动的元素

<div Class="question-item" draggable="true">Box 1: Milk was a bad choice.</div>
<div class="question-item" draggable="true">Box 2: I'm Ron Burgundy?</div>
<div class="question-item" draggable="true">Box 3: You ate the entire wheel of cheese?     </div>
<div class="question-item" draggable="true">Box 4: Scotch scotch scotch</div>

我有以下事件处理程序:

var $questionItems = $('.question-item');

$questionItems
  .on('dragstart', startDrag)
  .on('dragend', removeDropSpaces)
  .on('dragenter', toggleDropStyles)
  .on('dragleave', toggleDropStyles);


function startDrag(e)
  console.log('dragging...');
  addDropSpaces();
  e.stopPropagation();


function toggleDropStyles()
  $(this).toggleClass('drag-over');
  console.log(this);



function addDropSpaces()
  $questionItems.after('<div class="empty-drop-target"></div>');


function removeDropSpaces()
  console.log("dragend");
  $('.empty-drop-target').remove()

为什么它只适用于第一个可拖动的。如果我拖动说最后一个可拖动的 - dragend 事件会立即触发。 (顺便说一句,我不想​​使用 jQuery UI)

这对我来说毫无意义 - 它看起来像一个错误。

我在 OSX 上使用 Chrome v 30。

这里是 JSFiddle 的链接:http://jsfiddle.net/joergd/zGSpP/17/

(编辑:这是对以下问题的重复:dragend, dragenter, and dragleave firing off immediately when I drag - 但我认为原始海报可以使用 jQuery UI,而我希望它是 html5 原生的)

【问题讨论】:

【参考方案1】:

正如我在主题 dragend, dragenter, and dragleave firing off immediately when I drag 中提到的,对我来说解决问题(看起来是 Chrome 错误)的方法是在处理程序中添加一个 10 毫秒的 setTimeout 并在该超时内操作 DOM。

【讨论】:

为了可能缩小问题范围,我在我的案例中观察到(React,导致子树崩溃的 Redux 操作),只有在 DOM 修改后滚动条触及底部时才会出现此问题,这会导致拖动位置以跳转到相对于容器的不同位置。我假设浏览器引擎将其视为不一致并取消拖动操作,这将解释行为和解决方法。以相同的方式修改 DOM,但稍后是正常的鼠标移动。我假设如果修改是在拖动的项目上方完成的,也会发生同样的情况。 我发现将超时设置为 0 甚至可以。【参考方案2】:

我没有直接的解决方案,但是在 dragStart 事件处理程序中更改 DOM 会导致此问题,并且任何更改 DOM 的代码都应该真正进入 dragEnter 事件处理程序 - 这样做会触发更多拖放事件可靠。

不确定这是否是设计使然——不过感觉有点像错误。

【讨论】:

【参考方案3】:

这是一个已知的 chrome 问题。问题是,正如 Joerg 提到的那样,您在 dragstart 上操纵了 dom。

你可以这样做,但你需要超时。

【讨论】:

【参考方案4】:

刚刚遇到同样的问题。我通过将元素位置更改为在 dragStart 中固定来操作 DOM。我使用 Ivan 的回答解决了我的问题,如下所示:

/* This function produced the issue */
function dragStart(ev) 
    /* some code */
    myElement.style.position="fixed";


/* This function corrected issue */
function dragStart(ev) 
    /*some code */
    setTimeout(function changePos() 
        myElement.style.position="fixed";
        , 10);

您的问题的答案似乎是

function startDrag(e)
  console.log('dragging...');
  setTimeout(addDropSpaces(),10);
  e.stopPropagation();


【讨论】:

以上是关于HTML5 dragend 事件立即触发的主要内容,如果未能解决你的问题,请参考以下文章

dragend 和 drop 事件之间是不是有定义的顺序?

原生 drag drop HTML5

当 iframe 在拖放功能中移动时,Chrome 中的 Dragend 事件未触发

HTML5拖拽/拖放(drag & drop)详解

js拖放事件详解及实战

HTML5拖放-当Angular移动或删除源元素时不会触发“dragend”