属性更改后JQuery函数仍在运行

时间:2014-06-15 01:13:58

标签: javascript jquery

我的页面上有一个菜单。单击每个菜单项时,它将调用以下函数之一:

$('.sideNav1').click(function(){
    $('.sideNav1').attr('class','selected1');
    $('.selected2').attr('class','sideNav2');
    $('.selected3').attr('class','sideNav3');
    alert("1 selected");
    return false;
});

$('.sideNav2').click(function(){
    $('.sideNav2').attr('class','selected2');
    $('.selected1').attr('class','sideNav1');
    $('.selected3').attr('class','sideNav3');
    alert("2 selected");
    return false;
});

$('.sideNav3').click(function(){
    $('.sideNav3').attr('class','selected3');
    $('.selected2').attr('class','sideNav2');
    $('.selected1').attr('class','sideNav1');
    alert("3 selected");
    return false;
});

HTML:

<div class="sideNav1">
Nav 1
</div>
<div class="sideNav2">
Nav 2
</div>
<div class="sideNav3">
Nav 3
</div>

更改属性后(根据chrome中的dev工具确实发生),我希望所选的div在点击时不执行任何操作。相反,它的行为就像没有属性更改一样,click()事件监听器仍然被调用.sideNav...再次运行该函数。

这里有什么我可能会遗失的吗?

3 个答案:

答案 0 :(得分:3)

jQuery静态事件处理程序(您正在使用的类型),在您第一次运行代码时绑定事件处理程序ONCE。在此之后对类名的任何更改都是无关紧要的,并且不会以任何方式影响事件处理程序。

对于传播的事件,您可以使用委托事件处理,它会评估每个事件的选择器匹配。在委派事件处理中,将事件绑定到静态父对象(在安装事件处理程序时其DOM元素存在且在任何时候未重新创建的对象),并使用委派形式的.on()

在您的情况下,您必须选择静态父级的选择器并使用以下内容:

$(some parent selector).on("click", ".sideNav1", function() {...});

虽然(由于性能原因在大页面中)使用比<body>元素更近的父级,但您甚至可以这样做:

$(document.body).on("click", ".sideNav1", function() {...});

然后,只有当目标对象具有.sideNav1类名时才会调用事件处理程序,而不是当它没有时。

委派事件处理的方式是:

  1. “click”事件等某些事件会在父链上传播。在目标对象上调用它们之后,然后在链上的任何父对象上调用它们直到document对象,或直到有人在其上调用.stopPropagation()

  2. 因此,如果在父对象上安装特定事件的事件处理程序,则可以看到子对象上发生的所有事件(假设没有人在其上调用.stopPropagation())。

  3. 使用委托形式的.on() jQuery将检查在父项上调用的每个事件,以查看事件的原始目标是否与传递的第二个选择器匹配,并在运行时检查事件。因为此检查在事件分发时是实时的,所以它会受到您对DOM元素所做的任何动态更改的影响(如您的情况)。

  4. 您可以在这些参考资料中阅读有关委托事件处理的更多信息:

    jQuery .live() vs .on() method for adding a click event after loading dynamic html

    jQuery selector doesn't update after dynamically adding new elements

    jQuery .on does not work but .live does

    Does jQuery.on() work for elements that are added after the event handler is created?

    JQuery Event Handlers - What's the "Best" method

    这些答案中更常见的情况是在安装事件处理程序后添加或重新创建的DOM元素,但问题几乎与修改它们上的类并期望事件的DOM元素相同处理者改变他们的行为。


    仅供参考,我通常建议您使用.addClass().removeClass()代替.attr(),因为这样可以让程序的其他部分在这些对象上使用其他类(用于样式或其他原因)。

答案 1 :(得分:0)

如果你向所有div添加一个sideNav类,你可以这样做:

$('.sideNav').click(function(){
    $('.sideNav').removeClass("selected");
    $(this).addClass("selected");

});

Jsfiddle示例:http://jsfiddle.net/Tec3D/

答案 2 :(得分:-1)

好的,我从现场变为现在......

   $(document).on('click','.sideNav1',function(){
    $(this).unbind('click').attr('class','selected1');
    $('.selected2').attr('class','sideNav2').bind('click');
    $('.selected3').attr('class','sideNav3').bind('click');
    alert("1 selected");
    return false;
});

$(document).on('click','.sideNav2',function(){
     $(this).unbind('click').attr('class','selected2');
    $('.selected1').attr('class','sideNav1').bind('click');
    $('.selected3').attr('class','sideNav3').bind('click');
    alert("2 selected");
    return false;
});

$(document).on('click','.sideNav3',function(){     
    $(this).unbind('click').attr('class','selected3');
    $('.selected2').attr('class','sideNav2').bind('click');
    $('.selected1').attr('class','sideNav1').bind('click');
    alert("3 selected");
    return false;
});

http://jsfiddle.net/BHL84/14/