如何在动态创建子元素时避免再次调用hover / mouseenter

时间:2015-07-21 23:16:45

标签: javascript jquery jquery-hover

每当用户将鼠标悬停在A上时,我就会在元素内动态创建一个框,比如A,然后用鼠标移动框B。 B只应在用户悬停在A上时出现(即在鼠标移动时将其删除)。

不幸的是,如果我在B中动态创建元素,当鼠标移过它们时,会再次调用悬停事件(创建一个新的B)。当我在鼠标移动中动态创建B的子项时,似乎会发生此问题。起初我认为这与冒泡有关,需要委托,但现在我觉得这与我正在清空盒子并再次填充它的事实有关(从而导致悬停事件再次开火)?

这个例子说明了我遇到的问题:

https://jsfiddle.net/shzy6gtx/

function positionBox(element, position) {
    element.css({
        top: position - element.parent().offset().top - 10,
    });
    element.empty();
    jQuery('<span />').appendTo(element).text(position);    
}

$(document).bind('mousemove', function(e) {
    if ($('#theBox').length <= 0)
        return;
    positionBox($('#theBox'), e.pageY);
});

$('.hover').hover(function(e) {
    var innerBox = jQuery('<div />', {
        id: 'theBox',
        class: 'inner',
    }).appendTo(this);
    positionBox(innerBox, e.pageY);
}, function(e) {
    $('#theBox').remove();
});

这是它应该如何工作(没有动态创建的span标签):

https://jsfiddle.net/dffyt6gx/

如果这是我无法解决的问题,那么如何才能实现呢?

3 个答案:

答案 0 :(得分:1)

对我来说,问题实际上看起来都是:

  1. 事件冒泡问题。
  2. 重复快速创建位置跨度的问题 我的理论是,当鼠标悬停在位置标签上时标签被.empty()销毁,并且它没有再次快速地添加回来,这将被视为另一个鼠标输入事件。
  3. 现在1.只需添加

    即可解决
    if (e.delegateTarget != e.target)
            return;
    

    到悬停事件处理程序。您可以注意到问题的发生频率较低。

    For 2.

    • 一个简单的解决方案是每次移动鼠标(和B)时再次创建标签。 看看https://jsfiddle.net/IARI/w8y1y3vt/

      如果由于某种原因你想要或必须在B内创建元素,每次这都不会有帮助。但是,如果有可能不重新创建它们,我建议你这样做,只是出于性能原因。

    • 如果只是检查B是否存在是一个选项,那么它也可以解决它,同时允许您重新创建位置标签 - https://jsfiddle.net/IARI/shzy6gtx/6/

答案 1 :(得分:0)

不知道这是否可以帮到你,但是你要为每个div分配一个#id并尝试使用这些元素,#id在DOM中必须是唯一的。

    $(document).bind('mousemove', function(e) {
    if ($('.inner').length <= 0)
        return;
    positionBox($('.inner'), e.pageY);
});

$('.hover').hover(function(e) {
    var innerBox = jQuery('<div />', {
        id: 'theBox',
        class: 'inner',
    }).appendTo(this).click(function(e) {
    });
    positionBox(innerBox, e.pageY);
}, function(e) {
    $('.inner').remove();
});

也许这可以给你一个线索

添加了fiddle

答案 2 :(得分:0)

您可以移出处理程序。

**$('body').on('click','#theBox', function(e){
    alert('event handler'); });**

$('.hover').hover(function(e) {
    var innerBox = jQuery('<div />', {
        id: 'theBox',
        class: 'inner',
    }).appendTo(this);
    jQuery('<span />').appendTo(innerBox).text('number');
    positionBox(innerBox, e.pageY);
}, function(e) {
    $('#theBox').remove();
});