You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

jQuery UI贪婪式droppable未按预期工作问题排查

解决Droppable Greedy属性不生效,父级与子级Drop事件同时触发的问题

问题分析

你遇到的核心问题是:尽管给新生成的子级droppable设置了greedy: true,但拖拽元素到子级droppable上时,父级容器(#main_droppable)的drop事件还是会跟着触发。这是因为greedy属性的设计是阻止事件向上冒泡到父级droppable,但你的子级drop事件没有明确完成事件传播的阻断,导致父级事件仍然被触发。

解决方案

在子级droppable的drop事件处理函数中,添加event.stopPropagation()(仅阻止事件冒泡)或者直接return false(同时阻止默认行为和事件冒泡),就能确保只有子级的drop事件被执行,父级事件不会被触发。

修改后的完整代码

HTML

<div id="main_droppable"></div>
<ul>
  <li class="item" data-id="1">1</li>
  <li class="item" data-id="2">2</li>
  <li class="item" data-id="3">3</li>
  <li class="item" data-id="4">4</li>
  <li class="item" data-id="5">5</li>
</ul>

JavaScript

$(".item").data("active", false);

$(".item").draggable({
  helper: "clone",
  appendTo: "#main_droppable",
  scroll: false,
  start: function(event, ui) {
    if($(this).data("active") == false) {
      $(this).fadeTo(100, 0.2);
    } else {
      return false;
    }
  },
  revert: function(is_valid_drop) {
    if(!is_valid_drop) {
      $(this).fadeTo(100, 1).data("active", false);
      return true;
    } else {
      $(this).data("active", true);
    }
  }
});

$("#main_droppable").droppable({
  drop: function(event, ui) {
    console.log("drop main");
    addNewItem(ui.helper);
    return false;
  }
});

function addNewItem($oldItem) {
  var $newItem = $oldItem.clone(false).fadeTo(100, 1).data("active", true);
  $oldItem.remove();
  
  $newItem.draggable({
    containment: "parent",
  });
  
  $newItem.droppable({
    greedy: true,
    drop: function(event, ui) {
      // 关键:阻止事件向上冒泡到父级droppable
      event.stopPropagation();
      console.log("drop item");
      
      $(this).fadeTo(100, 0, function() {
        var $originalItem = $("ul").find(".item[data-id=" + $(this).data("id") + "]");
        $originalItem.fadeTo(100, 1).data("active", false);
        $("#main_droppable").find(".item[data-id=" + $originalItem.data("id") + "]").remove();
      });
      
      addNewItem(ui.helper);
    }
  });
  
  $("#main_droppable").append($newItem);
}

CSS

#main_droppable {
  border: 1px solid red;
  min-height: 50px;
}

.item {
  display: inline-block;
  border: 1px solid blue;
  width: 25px;
  height: 25px;
}

原理说明

greedy: true的作用是让子级droppable优先捕获drop事件,但在某些场景下,事件冒泡的机制还是会让父级事件被触发。通过在子级drop事件中调用event.stopPropagation(),我们明确切断了事件向上传播的路径,确保父级容器的drop事件不会被执行。如果你需要同时阻止默认行为,也可以用return false替代event.stopPropagation(),它在jQuery事件处理中会同时完成两种阻断操作。

内容的提问来源于stack exchange,提问作者Matías Cánepa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:36:26