I'm going to assume that you want the event to fire only once PER matched element rather than unbind entirely on the first click.
I'd implement it like so:
$('#container').delegate('.children', 'click', function() {
if($(this).data('clicked')) {
return;
}
// ... your code here ...
$(this).data('clicked', true);
});
This will fire only once per element. Technically, it fires everytime but is flagged the first time it is clicked so the code will not execute again.
The inherent problem of simulating a .one() handler w/ delegate is that using .one() each element that was matched in the selector is bound its own event handler. So when it is fired for the first time it unbinds/removes the handler from that element. You can't do that with .delegate() because only a SINGLE handler is being used for ALL the matched elements.
While the code above simulates it perfectly, it is still somewhat hackish because it doesn't literally do the same thing that .one() does (unbinding an event handler).
// define output element
var $output = $('div#output');
// attach delegated click handler
$(document).on('click', 'button', function() {
// define clicked element
var $this=$(this);
// if this element has already been clicked, abort
if ($this.data('clicked')) {
return false;
}
// perform click actions
$output.append("clicked " + $this.html() + "<br />");
// mark this element as clicked
$this.data('clicked',true);
});
Since this post is a few years old, I just wanted to provide a complete updated example for more contemporary readers (2015). The logic is no different from the other answers here, but jQuery's methods have evolved since 2011. Specifically:
As of jQuery 1.7, .delegate() has been superseded by the .on() method. jQuery delegate()
// define output element
var $output = $('div#output');
// attach delegated click handler
$(document).on('click', 'button', function() {
// define clicked element
var $this=$(this);
// if this element has already been clicked, abort
if ($this.data('clicked')) {
return false;
}
// perform click actions
$output.append("clicked " + $this.html() + "<br />");
// mark this element as clicked
$this.data('clicked',true);
});
发布评论
评论(3)
我假设您希望事件仅在每个匹配元素上触发一次,而不是在第一次单击时完全取消绑定。
我会像这样实现它:
每个元素只会触发一次。从技术上讲,它每次都会触发,但在第一次单击时会被标记,因此代码不会再次执行。
使用委托模拟 .one() 处理程序的固有问题是,使用 .one() 选择器中匹配的每个元素都绑定其自己的事件处理程序。因此,当第一次触发它时,它会从该元素中解除绑定/删除处理程序。您不能使用 .delegate() 执行此操作,因为只有一个处理程序用于所有匹配的元素。
虽然上面的代码完美地模拟了它,但它仍然有点hackish,因为它实际上并没有执行与 .one() 相同的操作(解除绑定事件处理程序)。
I'm going to assume that you want the event to fire only once PER matched element rather than unbind entirely on the first click.
I'd implement it like so:
This will fire only once per element. Technically, it fires everytime but is flagged the first time it is clicked so the code will not execute again.
The inherent problem of simulating a .one() handler w/ delegate is that using .one() each element that was matched in the selector is bound its own event handler. So when it is fired for the first time it unbinds/removes the handler from that element. You can't do that with .delegate() because only a SINGLE handler is being used for ALL the matched elements.
While the code above simulates it perfectly, it is still somewhat hackish because it doesn't literally do the same thing that .one() does (unbinding an event handler).
由于这篇文章已有几年历史,我只是想为更多当代读者提供一个完整的更新示例(2015)。其逻辑与此处的其他答案没有什么不同,但 jQuery 的方法自 2011 年以来一直在发展。具体来说:
Since this post is a few years old, I just wanted to provide a complete updated example for more contemporary readers (2015). The logic is no different from the other answers here, but jQuery's methods have evolved since 2011. Specifically:
我确信有一种简洁的方法可以做到这一点,但一种简单的方法是这样的:
编辑:感谢下面的评论,我决定使用数据,现在这不'不要为了 w3c 标准而把 DOM 搞砸。
I'm sure there is a neat way of doing it, but a simple way to do it would be something like this:
EDIT: Thanks to the comments below I decided to use data, now this doesn't screw the DOM all up for w3c standards.