有没有一种方法可以在任何事件被触发时只执行一次函数?
例如,如果我有以下函数:(在jsfiddle上的演示)
$('input').one('mouseup keyup', function(e){
console.log(e.type);
});
无论哪个事件触发了它,我希望只调用该函数一次。
但根据 .one() 的文档:
如果第一个参数包含多个空格分隔的事件类型,则对于每种事件类型都会调用事件处理程序一次。
因此,当前该函数将针对每种事件类型触发一次。
有没有一种方法可以在任何事件被触发时只执行一次函数?
例如,如果我有以下函数:(在jsfiddle上的演示)
$('input').one('mouseup keyup', function(e){
console.log(e.type);
});
无论哪个事件触发了它,我希望只调用该函数一次。
但根据 .one() 的文档:
如果第一个参数包含多个空格分隔的事件类型,则对于每种事件类型都会调用事件处理程序一次。
因此,当前该函数将针对每种事件类型触发一次。
不要使用.one
,而是使用.on
并手动使用.off
来取消绑定。
$('input').on('mouseup keyup', function(e){
console.log(e.type);
$(this).off('mouseup keyup');
});
Fiddle: http://jsfiddle.net/23H7J/3/
使用命名空间可以更加优雅地完成这项工作:
$('input').on('mouseup.foo keyup.foo', function(e){
console.log(e.type);
$(this).off('.foo');
});
这使我们能够使用单个标识符(foo)来删除任意数量的绑定,并且不会影响元素可能拥有的任何其他mouseup或keyup绑定。
很棒的答案!为了将它们封装成一个函数,这里有一个基于当前答案的jQuery扩展:
//The handler is executed at most once per element for all event types.
$.fn.once = function (events, callback) {
return this.each(function () {
$(this).on(events, myCallback);
function myCallback(e) {
$(this).off(events, myCallback);
callback.call(this, e);
}
});
};
$('input').once('mouseup keyup', function(e){
console.log(e.type);
});
额外福利:通过将原始处理程序传递给off函数,可以使此特定函数的处理程序仅分离。否则,您需要自定义命名空间。
另外,如果您希望处理程序仅在任何元素触发任何事件并立即分离时仅触发一次,则只需从扩展中删除each
,如下所示:
//The handler is executed at most once for all elements for all event types.
$.fn.only = function (events, callback) {
var $this = $(this).on(events, myCallback);
function myCallback(e) {
$this.off(events, myCallback);
callback.call(this, e);
}
return this
};
$('#someParent').once('keyup etc', '.someChildrenOfParent'), function(e){ doStuff(); });
这种语法来工作? - Drew$.fn.onSingle = function(events, callback){
if ("function" == typeof(callback)) {
var t = this;
var internalCallback = function(event){
$(t).off(events, internalCallback);
callback.apply(t, [event]);
setTimeout(function(){
$(t).on(events, internalCallback);
}, 0);
};
$(t).on(events, internalCallback);
}
return $(this);
};
它的工作原理是通过使用internalCallback
函数暂时禁用事件,并异步(setTimeout
)再次启用。
这个线程中的大多数其他建议会在目标上永久禁用所有未来事件。然而,虽然OP似乎对之前的答案满意,但他的问题并未提到永久禁用事件。
$('input').off();
。$('input').on('keyup paste input change', function(e){
var oldValue = $(e.target).data('oldvalue');
var newValue = $(e.target).val();
if (oldValue === newValue) //nothing has changed
return;
$(e.target).data('oldvalue',newValue); //store the newly updated value
//proceed with the rest of the function
});
var selector = document.querySelector('input')
selector.addEventListener('keyup', updateElement);
selector.addEventListener('paste', updateElement);
selector.addEventListener('input', updateElement);
selector.addEventListener('change', updateElement);
function updateElement(e){
var oldValue = e.target.getAttribute('oldvalue');
var newValue = e.target.value;
if (oldValue === newValue) //nothing has changed
return;
console.log (newValue);
e.target.setAttribute('oldvalue', newValue); //store the newly updated value
//proceed with the rest of the function
}
mouseup
来检测可能的右键单击>粘贴,因为鼠标可能在输入框之外释放。为了安全起见,最好使用keyup
、paste
、input
和change
,就像我在上面的代码中所做的那样。mouseup
和keyup
事件,并且我想只处理一次,无论哪个被触发,比较oldValue === newValue
并不能解决问题。因此,值得撤下答案并发布自己的问题,以阐明您要解决的问题。 - KyleMit
$('input').on('mouseup keyup', function foo(e) { $(this).off('mouseup keyup', foo); });
- Dan