我在执行以下代码时遇到一些问题:
var i = 1;
$('.hello:not(.selected)').on('click',function(){
$(this).addClass('selected');
console.log(i++);
});
问题是这个代码应该在选择的类添加后触发一次,但是它执行了很多次,我只想让 i 变量不增加。换句话说,我正在尝试执行以下操作(这有效,但我不想使用live函数,因为它已弃用):
$('.hello:not(.selected)').live('click', function () {
$('.hello').removeClass('selected');
$(this).addClass('selected');
...
});
非常感谢您的回复, ķ
答案 0 :(得分:17)
您的代码正在使用当前符合此条件的元素集:
$('.hello:not(.selected)')
并设置此事件处理程序永恒:
.on('click',function(){
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
});
特别重要的是,一旦处理程序在元素上设置,它将继续处于活动状态,即使稍后该元素不再满足条件(在这种情况下,通过获取selected
类)。
有几种方法可以实现所需的行为。一种方法是动态检查“过滤器”条件是否仍然保留在事件处理程序中:
$('.hello').on('click',function(){
if($(this).hasClass('selected')) {
return;
}
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
});
另一个是委托事件 - 在这种情况下,父元素将被通知其中一个后代上的事件,它将动态检查所述后代是否满足过滤条件之前决定触发事件处理程序(代码从Ben Lee的答案中无耻地粘贴):
$('body').on('click', '.hello:not(.selected)', function() {
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
});
答案 1 :(得分:7)
问题是事件处理程序不会因为您更改类而被删除。您将事件附加到元素,并且它们永远存在于那里。
要解决这个问题,您可以在每个事件句柄上测试“selected”类:
$('.hello:not(.selected)').on('click',function(){
if ($(this).hasClass('selected')) {
$(this).addClass('selected');
$(this).css({opacity : 0.5});
console.log(i++);
}
});
但是为了提高效率和简化代码,您可能应该委托:
$('body').on('click', '.hello:not(.selected)', function() {
var $self = $(this);
$self.addClass('selected');
$self.css({opacity : 0.5});
console.log(i++);
});
我使用“body”作为附加此委托的元素,但您应该使用树中较低的内容,例如“.hello”元素的父级或祖父级。这只附加一个事件处理程序,并依赖冒泡来测试每个元素实时更改时的选定状态。
另请注意,我缓存了var $self = $(this)
;这也是为了提高效率,所以你最终不需要jQuery扩展元素。