如何解决动态创建的droppable的over事件无法被第一时间触发的问题?

我使用jqui中的droppable小部件。

我的父元素“Div”是一个droppable对象,当accept对象“ball”进入其中时会在父元素Div内创建另一个同样是droppable的子元素“circle”,这个子元素同样绑定了一个over事件,当“ball”对象进入“circle”时,会触发“进球了”函数

但是,我发现:当我移动ball进入Div内,circle产生了,而此时我移动ball进入circle内,却没有正确触发“进球”事件(事实上,任何绑定在"circle"上的droppable事件都没有触发),必须先松开处于拖拽中的ball,再点击ball拖拽,使其进入circle中,才能正确触发circle的over事件。

然而,这并不符合我的预期,我希望当ball进入Div内,再进入circle时,能够直接触发这个事件,而不是先松开,再拖拽,随后触发这个事件,我该如何解决这个问题?感谢任何愿意提出的建议!

阅读 590
avatarAI BotBETA

这个问题似乎是由于jQuery UI的droppable组件在处理拖动事件时存在一些困难。当你在拖动一个元素并放入另一个droppable元素时,它可能无法正确地触发那个元素的"over"事件。

你可以尝试使用一个叫做"activate"的事件来代替"over"。这个事件在元素被放置并且是目标元素的时候被触发,所以它可能能解决你的问题。以下是你如何修改你的代码的一个示例:

$("#Div").droppable({
    accept: "#ball",
    activate: function(event, ui) {
        var circle = $(event.target).find("#circle");
        if(circle.length > 0) {
            circle.droppable("option", "over", function(event, ui) {
                // 这里写你的"进球了"函数
                console.log("进球了");
            });
        }
    }
});

在这个例子中,当#ball被拖动到#Div并且#circle被创建时,我们检查#circle是否存在,如果存在,我们就在#circle上设置"over"事件。这样,当你将#ball拖到#circle时,应该能够立即触发"进球了"函数。

然而,这个解决方案有一个局限性,就是当#ball被放入#circle后,如果你再把#ball从#circle中取出,#circle的"over"事件将不会被触发,除非你再次将#ball放入#circle。这是因为droppable组件在初始化的时候会为每个可接受的元素创建一个新的"over"事件监听器,而这个监听器只在元素第一次被放置的时候被触发。

为了解决这个问题,你可能需要使用一个自定义的事件处理器,而这个处理器可以在每次#ball被放入#Div和#circle的时候被触发。这样,无论何时#ball被移动到#Div或者#circle,你都能确保你的"进球了"函数会被正确地触发。

2 个回答

我最终通过使用draggble元素的refreshPositions属性解决了这个问题,当refreshPositions为true时,拖拽draggable元素会使其计算所有可放置的位置,从而解决了新创建的circle无法被检测到的问题。然而,据我所知,当div内的circle数量过多时,这会大幅影响到性能。如果任何人有更高的方法解决这个问题,我非常欢迎!

遇到的问题可能是由于事件冒泡和事件捕获的机制导致的。默认情况下,当您拖动"ball"进入"circle"时,"circle"上的事件处理程序可能无法触发,因为拖拽事件通常被处理为拖拽操作,而不是鼠标悬停事件。

要解决这个问题,您可以尝试以下方法:

使用事件代理:将"circle"上的事件处理程序绑定到其父元素(“Div”)上,然后在事件处理程序中检查拖拽元素是否进入了"circle"。这样,无论"ball"进入哪个子元素,事件都会被正确触发。

$("#Div").on("mouseover", ".circle", function() {

// 在这里处理"进球了"事件

});
手动触发事件:在"ball"进入"circle"时,您可以手动触发"circle"上的事件,以确保事件被正确处理。您可以使用jQuery的 .trigger() 方法来实现这一点。

$("#ball").on("dragover", function(event) {

// 检查是否进入了"circle"
if (isInsideCircle(event)) {
    // 手动触发"circle"上的事件
    $("#circle").trigger("mouseover");
}

});

function isInsideCircle(event) {

// 检查拖拽元素是否在"circle"内
// 实现这个函数以匹配您的页面结构

}
在 isInsideCircle 函数中,您需要根据页面结构和坐标位置来检查拖拽元素是否进入了"circle"。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题