嵌套的 Ember.View dragEnter dragLeave 调用顺序错误?

Posted

技术标签:

【中文标题】嵌套的 Ember.View dragEnter dragLeave 调用顺序错误?【英文标题】:Nested Ember.View dragEnter dragLeave called in wrong order? 【发布时间】:2013-11-18 12:06:00 【问题描述】:

我正在使用 html5 drag and drop api 创建日历。

我正在使用dragEnterdragLeave 来设置接收元素的样式并确定droppablity。

接收可放置元素有子元素,并且在拖动子元素时调用dragLeave。这个问题知道和描述here.

我尝试的解决方案是在子级上添加dragLeavedragEnter 事件并将逻辑传递回父视图。

这里是代码。 http://jsbin.com/iHaNuPo/17

问题是子级上的 `dragEnter' 在父级上的 'dragLeave' 之前被调用。

这是事件的顺序。

#in from outside parent to over child
1. parent-enter 
2. child-enter 
3. parent-leave
#out from over child to outside parent
1. parent-enter
2. child-leave
3. parent-leave

这是一个错误吗?

任何人都知道一种 Ember'ish 方法来防止父级的 dragLeave 事件在将鼠标悬停在子级上时触发?

或者修复事件dragLeavedragEnter触发顺序的方法?

我应该放弃 html5 原生拖放并使用 jquery ui draggable/droppable 吗?

编辑

根据 Woody 的回答,这是一个工作示例。

http://jsbin.com/OjAGabUj/22

【问题讨论】:

你应该放弃原生 d-n-d 吗?如果您使用具有垫片的库,它可能会确保您的兼容性。否则,无论如何它都会服从原生。 【参考方案1】:

希望这可以帮助你,虽然它不是 Ember,也许你可以利用它。我有相当多的 HTML5 拖放经验,这有点令人厌烦,但如果你想要像跨窗口拖放这样酷的东西,我认为值得付出努力。

var ignoreNextLeave = false;

$("#outerDragTarget").on("dragenter", function(ev) 
   // not interested in dragleaves from my children...
   if (ev.target !== this) 
      ignoreNextLeave = true;
   

   $(this).addClass("dragover");

).on("dragleave", function(ev) 

   if (ignoreNextLeave) 
      ignoreNextLeave = false;
      return;
   

   $(this).removeClass("dragover");
);

$("#innerDragTarget").on("dragleave", function(ev) 
  ev.stopPropagation();
);

你可以运行它here

诀窍是取消从内部元素传播dragleaves,并注意当drag enter 在父元素上触发并且目标不是父元素时,我们将获得一个我们不感兴趣的drag Leave。不是理想,但可以考虑到您可以使用的东西。

【讨论】:

太棒了!我添加了一个实现您的方法的示例。 酷! HTML5 拖放在 IE 上有一些粗糙的边缘和不完整的支持。从 IE10 开始,事情开始有所好转,尽管仍然存在一些问题,但大多数问题都可以解决。在过去的一年里,我在工作中花了很多时间处理这些东西,所以请查看我的其他问题和答案——它们或多或少包含了我学到的所有有用的东西:) 所以简而言之,如果可以的话,我会使用 HTML5 拖放,据我所知,没有可用的拖放框架使用本机拖放。如果您想跨窗口拖放或拖入另一个应用程序,本地拖放是唯一的游戏。 是的,它有点粗糙。我只使用 webkit,所以我将坚持使用 html5。您认为事件顺序(outerEnter、innerEnter、OuterLeave)是 chrome 中的错误还是 dnd 规范的一部分?谢谢! 这是规范中的预期行为。即使它确实违反直觉并且经常出现问题:/【参考方案2】:

我认为 Woody 的解决方案是正确的,但是如果您想节省几行代码并避免不得不直接摆弄子元素,您还可以使用引用计数解决方案:

$(".drop-target").on("dragenter dragleave", function (e)

  var dragHoverCount = Number($(this).data("dragHoverCount")) || 0;
  (e.type === "dragenter") ? dragHoverCount++ : dragHoverCount--;
  $(this).data("dragHoverCount", dragHoverCount);

  $(this).toggleClass("drag-hover", dragHoverCount > 0);

  e.preventDefault();
);

【讨论】:

以上是关于嵌套的 Ember.View dragEnter dragLeave 调用顺序错误?的主要内容,如果未能解决你的问题,请参考以下文章

如何防止dragleave干扰嵌套dropzone元素上的dragenter事件?

Ember.Container 的用途是啥

Ember.js:Handlebars 不显示任何内容

Ember.js 路由器:如何动画状态转换

dragenter/dragleave 防止 drop 发射

DragDrop - DragEnter/DragLeave 事件持续触发