不选择器,on()点击事件

Mar*_*iaZ 11 jquery

我在执行以下代码时遇到一些问题:

    var i = 1;  
$('.hello:not(.selected)').on('click',function(){
    $(this).addClass('selected');       
    console.log(i++);   
});
Run Code Online (Sandbox Code Playgroud)

问题是这个代码应该在选择的类添加后只触发一次,但是它执行了很多次,我只想让i变量不增加.换句话说,我正在尝试执行以下操作(有效,但我不想使用live函数,因为它已弃用):

$('.hello:not(.selected)').live('click', function () { 
   $('.hello').removeClass('selected');
   $(this).addClass('selected');
... 
});
Run Code Online (Sandbox Code Playgroud)

非常感谢您提前回复,k

Jon*_*Jon 19

您的代码采用当前满足此条件的元素集:

$('.hello:not(.selected)')
Run Code Online (Sandbox Code Playgroud)

为所有永恒设置此事件处理程序:

.on('click',function(){
    $(this).addClass('selected');
    $(this).css({opacity : 0.5});       
    console.log(i++);   
});
Run Code Online (Sandbox Code Playgroud)

特别重要的是,一旦处理程序设置在一个元素上,它将继续处于活动状态,即使稍后该元素不再满足条件(在这种情况下,通过获取selected类).

有几种方法可以实现所需的行为.一种方法是动态检查"过滤器"条件是否仍然保留在事件处理程序中:

$('.hello').on('click',function(){
    if($(this).hasClass('selected')) {
        return;
    }
    $(this).addClass('selected');
    $(this).css({opacity : 0.5});       
    console.log(i++);   
});
Run Code Online (Sandbox Code Playgroud)

另一种方法是委托事件 - 在这种情况下,父元素将被通知其中一个后代上的事件,并且它会在决定触发事件处理程序之前动态检查所述后代是否满足过滤条件(代码无耻地粘贴来自Ben Lee的回答):

$('body').on('click', '.hello:not(.selected)', function() {
    $(this).addClass('selected');
    $(this).css({opacity : 0.5});       
    console.log(i++);
});
Run Code Online (Sandbox Code Playgroud)


Ben*_*Lee 7

问题是事件处理程序不会因为您更改类而被删除.您将事件附加到元素,并且它们永远存在于那里.

要解决这个问题,您可以在每个事件句柄上测试"selected"类:

$('.hello:not(.selected)').on('click',function(){
    if ($(this).hasClass('selected')) {
        $(this).addClass('selected');
        $(this).css({opacity : 0.5});       
        console.log(i++);
    }
});
Run Code Online (Sandbox Code Playgroud)

但是为了提高效率和简化代码,你应该委托:

$('body').on('click', '.hello:not(.selected)', function() {
    var $self = $(this);
    $self.addClass('selected');
    $self.css({opacity : 0.5});       
    console.log(i++);
});
Run Code Online (Sandbox Code Playgroud)

我使用"body"作为附加此委托的元素,但是您应该使用树中较低的东西,例如".hello"元素的父级或祖父级.这只附加一个事件处理程序,并依赖冒泡来测试每个元素实时更改时的选定状态.

还要注意我缓存var $self = $(this); 这也是为了提高效率,所以你最终不需要jQuery扩展元素.