jQuery .live() 不起作用

5

我的实际问题是,jQuery的.live()方法无法工作。

这是我使用它的代码:

    jQuery.fn.sb_animateMenuItem = function()
    {
    var mousehoverColor = '#0089F7';
    var duration = 250;

    return this.each(function()
    {
        var originalColor = $(this).css('background-color');
        $(this).live('mouseover', function()
        {
            this.style.cursor = 'pointer';
            $(this).animate().stop();
            $(this).animate(
            {
                backgroundColor: mousehoverColor
            }, duration);
        });
        $(this).live('mouseout', function()
        {
            this.style.cursor = 'default';
            $(this).animate(
            {
                backgroundColor: originalColor
            }, duration);
        });
    });
};

这个代码片段可以通过以下方式在另一个页面中使用:
<script type="text/javascript" src="ui/js/jquery-1.4.2.js"></script>
<script type="text/javascript" src="ui/js/jquery-ui-1.8.1.custom.min.js"></script>
<script type="text/javascript" src="ui/js/color.js"></script>
<script type="text/javascript" src="engine/js/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="ui/js/ui.js"></script>
<script type="text/javascript">
    // UI effects
    $(document).ready(function()
    {
      $('button').sb_animateButton();
      $('input').sb_animateInput();
      $('.top_menu_item').sb_animateMenuItem();
      $('.top_menu_item_right').sb_animateMenuItem();
      $('.left_menu_item').sb_animateMenuItem();
    });
</script>

由于我的网站使用 AJAX 请求,所以我在第一个代码片段中使用了 .live 方法,但是当我加载页面时,按钮/输入标签没有应用效果。

如果我删除 .live 方法并使用“普通”方式,在第一个代码片段中定义的 UI 效果将被应用,但只有在任何 AJAX 请求之前加载的元素才会受到影响。加载 AJAX 请求后的元素不受第一个代码片段的影响(尽管它们具有相同的选择器)。

感谢您的帮助。

2个回答

16

简单来说,你不能像这样使用 .live(),它必须跟随某种选择器基础,这是来自 .live() 文档的说明

DOM 遍历方法不完全支持查找要发送到 .live() 的元素。相反,.live() 方法应该始终在选择器之后直接调用,就像上面的示例一样。

你正在对一个表示特定 DOM 元素的 jQuery 对象调用 .live(),而你需要获取插件运行的 .selector(如果有的话),当然这并不保证。然后使用 那个 选择器来调用 .live(),就像这样:

 jQuery.fn.sb_animateMenuItem = function() {
    $(this.selector).live(.....)
如果你考虑一下,.live() 是如何工作的呢?它监听事件冒泡,检查目标是否匹配选择器,如果是,则执行(在上下文中,这是另一个讨论)...... 如果你使用 $(DOMElement).live(),它会检查哪个选择器以确定是否应该执行呢?
我猜你可以根据内部元素uuid进行争论,这样做应该可以工作,但那只是.bind(),这将浪费更少的资源,因此.live()并不像那样做。

更新:由于我对最简单的实现方式很感兴趣,避免代码重复,这是你的插件版本,根据是否存在.live()可以使用的选择器动态选择使用.live().bind():

jQuery.fn.sb_animateMenuItem = function() {
  var mousehoverColor = '#0089F7';
  var duration = 250;
  var method = this.selector ? jQuery.fn.live : jQuery.fn.bind;
  method.apply(this, ['mouseover', function() {
     if(!jQuery.data(this, 'oColor'))
         jQuery.data(this, 'oColor', jQuery(this).css('background-color'));
     jQuery(this).stop(true).animate({ backgroundColor:mousehoverColor }, duration);
  }]);
  method.apply(this, ['mouseout', function() {
    jQuery(this).animate({ backgroundColor:jQuery.data(this, 'oColor') }, duration);
  }]);
  return this.css('cursor', 'pointer');
};

您可以查看这里的演示来了解两者的表现


非常赞同。从这个答案中学到了很多东西。也要给提问者点个赞。 - user113716
好吧...我尝试了两种方法,但它们都不起作用。我决定用另一种方式解决问题:https://dev59.com/NHA75IYBdhLWcg3w7tt6。 - siannone
@Silvio - 你有链接吗?你在这个问题之外还有其他影响它的因素。例如,你调用了其他函数,但这里没有它们的代码。 - Nick Craver
我仍然无法弄清楚问题所在。但是,我通过重新应用UI效果到由ajax函数加载的元素来解决它。 - siannone
@Nick - 我们还在讨论这个函数。我的意思是我找到了另一种方法:这是页面加载时应用效果的方式: $('button').sb_animateButton(); $('input').sb_animateInput(); 等等...因此,当我将HTML内容加载到页面中时,通过再次调用以下代码重新应用UI效果: $('button').sb_animateButton(); $('input').sb_animateInput();...以及通过ajax函数放置在页面中的新元素,如输入框和按钮,也会获得UI效果。再次感谢您的帮助。我会尝试在我的网站上实现您的方法。它可以被视为解决方案。 - siannone
显示剩余3条评论

5
您可以使用 .DELEGATE() 替代 .LIVE、.ON、.BIND。
例如:
$("body").DELEGATE($(this),"click","myfunction")

或者

$("body").DELEGATE($(this),"click",function () {
///code here
} )

谢谢,这个解决方案在动态添加内容时没有触发(结果是我犯了其他错误——错误地嵌套了一个表单),但知道这一点很有趣。 - Iain Collins

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接