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
相关产品推荐
相关产品推荐

