jQuery 不是选择器,on() 点击事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9478413/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
not selector, on() click event
提问by MariaZ
I am having some problems in executing the following code:
我在执行以下代码时遇到了一些问题:
var i = 1;
$('.hello:not(.selected)').on('click',function(){
$(this).addClass('selected');
console.log(i++);
});
The problem is that this code should trigger just ONE time after the class selected has added, but it is executing many times, I just want the ivariable not to increase. In other words, I am trying to do the following (which works, but i don't want to use the live function since it has deprecated):
问题是此代码应该在添加所选类后仅触发一次,但它执行了很多次,我只是希望i变量不要增加。换句话说,我正在尝试执行以下操作(有效,但我不想使用 live 函数,因为它已被弃用):
$('.hello:not(.selected)').live('click', function () {
$('.hello').removeClass('selected');
$(this).addClass('selected');
...
});
Thanks so much for your responses in advance, k
非常感谢您提前回复,k
回答by Jon
Your code is taking the set of elements that currentlysatisfy this criteria:
您的代码正在采用当前满足此条件的一组元素:
$('.hello:not(.selected)')
and setting up this event handler for all eternity:
并为所有永恒设置此事件处理程序:
.on('click',function(){
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
});
Particularly important is the fact that once the handler is set on an element, it will continue to be active even if later on that element no longer satisfies the criteria(in this case, by gaining the selected
class).
特别重要的是,一旦在元素上设置了处理程序,它就会继续处于活动状态,即使稍后该元素不再满足条件(在这种情况下,通过获得selected
类)。
There are several ways to achieve the desired behavior. One would be to dynamically check that the "filter" condition still holds inside the event handler:
有几种方法可以实现所需的行为。一种是动态检查“过滤器”条件是否仍然存在于事件处理程序中:
$('.hello').on('click',function(){
if($(this).hasClass('selected')) {
return;
}
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
});
Another would be to delegate the event -- in this case, a parent element would be notified of the event on one of its descendants and it would dynamicallycheck that said descendant satisfies the filter condition before deciding to trigger the event handler (code shamelessly pasted from Ben Lee's answer):
另一种方法是委托事件——在这种情况下,父元素将被通知其后代之一的事件,并在决定触发事件处理程序之前动态检查所述后代是否满足过滤条件(代码无耻地粘贴来自 Ben Lee 的回答):
$('body').on('click', '.hello:not(.selected)', function() {
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
});
回答by Ben Lee
The problem is the event handler doesn't get removed just because you change the class. You are attaching the events to the elements, and they stay there forever.
问题是事件处理程序不会因为您更改类而被删除。您将事件附加到元素上,并且它们永远留在那里。
To get around this, you could just test for the "selected" class on each event handle:
为了解决这个问题,您可以测试每个事件句柄上的“selected”类:
$('.hello:not(.selected)').on('click',function(){
if ($(this).hasClass('selected')) {
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
}
});
But for efficiency and simpler code, you should probably delegate this:
但是为了效率和更简单的代码,您可能应该委托:
$('body').on('click', '.hello:not(.selected)', function() {
var $self = $(this);
$self.addClass('selected');
$self.css({opacity : 0.5});
console.log(i++);
});
I used "body" as the element to attach this delegation, but you should probably use something lower in the tree, like a parent or grandparent of the ".hello" elements. This only attaches one event handler, and relies on bubbling to test the selected state of each element as they change in real time.
我使用“body”作为附加这个委托的元素,但你可能应该使用树中较低的东西,比如“.hello”元素的父或祖父。这仅附加一个事件处理程序,并依靠冒泡来测试每个元素实时更改时的选定状态。
Also note that I cached var $self = $(this)
; that was also for efficiency, so you don't end up jQuery-extending the element more than you need to.
另请注意,我缓存了var $self = $(this)
; 这也是为了提高效率,因此您最终不会对元素进行过多的 jQuery 扩展。