【问题标题】:JQuery - Hover event not firing on Hover outJQuery - 悬停事件未在悬停时触发
【发布时间】:2012-09-05 00:39:29
【问题描述】:

我正在实现我自己的“工具提示”,每次您将鼠标悬停在它上面时它都会创建一个新的 div 元素,并在悬停时将其删除。下面的代码是从我使用的代码中删除的,但它显示了问题:当用户慢慢地将鼠标放在 $('#' + fieldName) 对象上并移开对象时,这段代码非常有效,但是当你将鼠标移到对象,然后快速将其拉离工具提示不会被删除。有没有办法改进我的代码?

我尝试实现一个系统,在该系统中创建所有工具提示框并隐藏它们,然后在悬停时显示它们,但它带来了相同的问题,即鼠标快速离开对象并且悬停不触发。

$('#' + fieldName).hover(
    function () { /* Create new DOM element */
        /* My ajax stuff here */
        var data = 'test';
        var tooltipBox = $('<div id="' + fieldName + '_tooltip">' + data + '</div>');
        $("body").prepend(tooltipBox);
    },
    function () { /* Remove Tooltip from DOM */
        $('#' + fieldName + '_tooltip').remove();
    }
);

答案:

在 Robert Koritnik 和 sajawikio 的帮助下:

如果您需要在悬停时使用 AJAX 调用在悬停时制作工具提示,您可以做一个小技巧来使其工作。

var callingAjax = false;
var removeTooltip = false;
$('#tooltip').hover(
     function() {
          callingAjax = true;
          $.post(.. {
              callingAjax = false;
              /* do stuff */
              if(removeTooltip)
                   /* code to remove tooltip */
              removeTooltip = false;
          });
     },
     function() {
          if(callingAjax) 
              removeTooltip = true;
          else
              /* code to remove tooltip */
     }
);

【问题讨论】:

  • 我怀疑mouseleave事件没有被触发。在删除元素之前输入alert("out"); 以验证它。 fieldName 更可能发生更改,因此您尝试删除的元素不存在。我建议将工具提示作为插件实现。
  • @maenu:我宁愿选择console.log...
  • @maenu 我放了 alert(fieldName) 看看它是否保持不变,它总是被设置,但是,它也总是被调用。所以问题是 .remove();不工作。

标签: jquery


【解决方案1】:

您的代码有效

我已将您的代码放在JSFiddle 中并且可以正常工作,所以您一定有其他问题。我可以在链接上尽可能快地移动鼠标,但每次都会删除工具提示。

我正在使用 Chrome。你的药物是什么?

注意:我在 JSFiddle 中的代码与您的代码之间的唯一区别是我使用了 append,而您使用了 prepend。出于明显的原因,我已经改变了这一点。尝试改变它,你会明白为什么。但这两种方式都有效。

注意2:实际上如果你把append改为prepend,它实际上模拟了快速的鼠标移动,因为当一个对象被前置时,鼠标悬停在链接之外。因此,与其尽可能快地移动鼠标,不如移动元素来模拟相同的行为。

实际问题

问题是您在创建工具提示之前在悬停中执行其他操作。这是否是 Ajax 调用并不重要。它可能是任何异步的,因此 Javascript 线程可以执行下一个函数。如果执行的时间比您停留在元素上的时间长,您的鼠标移出想要删除尚未创建的内容(稍后会)。

两种可能的解决方案:

  1. 首先添加您的工具提示,然后执行其他内容。
  2. 在执行悬停事件后推迟 Ajax 调用。

警告

我强烈建议在悬停事件中不执行 ajax 代码,因为您可能会触发大量请求。实际上,不仅仅是浏览器可以处理的。如果您必须在悬停时执行 ajax 请求,请按以下方式执行:hover 触发并准备在其后立即执行的函数调用,但该函数仅在尚未进行时才会发出 Ajax 调用:

// variable outside of hover closures
var ajaxExecuting = false;

// code to put within your hover handler
setTimeout(function() {
    if (!ajaxExecuting)
    {
        ajaxExecuting = true;
        // do your AJAX stuff
    }
}, 0);

【讨论】:

  • +1 for ajaxExcecuting - 好主意 - 是的,如果将鼠标悬停在这么多东西上,一次执行 100 个 ajax 会很奇怪 - 非常好
【解决方案2】:

是的,有问题。让速度根本不是一个因素 - 不要让它碰运气,并确保当你悬停时,你的悬停激活 - 当你悬停时,你的悬停激活!万无一失!这样,您就不会像您所说的那样陷入“扩展”的困境!换句话说,“来回切换样式”一次执行一个事件,而不是使用持久处理程序。

(请参阅示例代码 - 如果您使用的元素当然更大,则效果很好) - http://jsfiddle.net/4jArC/

var fieldName = "whatever";

function b(evt) { /* Remove Tooltip from DOM */
    $('#' + fieldName + '_tooltip').remove();
    $(evt.currentTarget).one('mouseover',a);
}

function a (evt) { /* Create new DOM element */
    /* My ajax stuff here */
    var data = 'test';
    var tooltipBox = $('<div id="' + fieldName + '_tooltip">' + data + '</div>');
    $("body").prepend(tooltipBox);
    $(evt.currentTarget).one('mouseout',b);
}

$('#' + fieldName).one('mouseover', a);
​

【讨论】:

  • 好的,所以你提供了一个替代解决方案,我只在极端情况下推荐它。 更重要的是,您在开始时声明是的,存在问题。您介意解释问题的原因和位置吗?因为我没有看到问题......而且我当然也没有看到对此的解释。 :)
  • 问题是你对你自己的代码的描述!有时,“当您将鼠标移到对象上然后快速将其从工具提示中拉出时,工具提示不会被删除” - 您的代码可能会发生这种情况,您看到它发生了,这就是您这么说的原因,对吧?
  • 更具体地说 - 你的悬停代码太异步了,所以如果你的 mouseout 在你的鼠标悬停之前执行,那么你会卡在工具提示上。
  • 在我的版本中,会发生以下情况:好的,当我悬停时,然后创建悬停事件。好的,如果我将鼠标悬停在外面,则创造机会重新悬停。它保证您不会“卡住”
  • 哦,我的坏 nvm 你不是原始海报 - nvm - 但我知道因为我使用 OP 的样式代码(当我刚开始时),我一直有这个问题,直到我开始做它与这些类型的听众。给定足够多的元素和足够多的其他因素,您将看到 OP 的代码会出现错误并“卡住”,而不会像 OP 指出的那样删除工具提示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-02
  • 1970-01-01
相关资源
最近更新 更多