jQuery On - 使用多种事件类型触发一次

时间:2014-07-05 17:55:11

标签: javascript jquery events

根据docs for one

  

如果第一个参数包含多个以空格分隔的事件类型,则事件处理程序对每个事件类型称为一次。

有什么方法可以在引发任何事件时触发一个函数吗?

示例:

$('input').one('mouseup keyup', function(e){ 
    console.log(e.type);
});

我想只调用一次该函数,无论哪个事件触发它。

目前,该功能将针对每种事件类型触发一次。

Demo in Fiddle

  

注意:我不是在这里寻找 focus 事件......这只是一个例子。

5 个答案:

答案 0 :(得分:14)

不使用.one,而是使用.on并使用.off手动删除绑定。

$('input').on('mouseup keyup', function(e){
    console.log(e.type);
    $(this).off('mouseup keyup');
});

小提琴:http://jsfiddle.net/23H7J/3/


使用命名空间可以更优雅地完成:

$('input').on('mouseup.foo keyup.foo', function(e){
    console.log(e.type);
    $(this).off('.foo');
});

这允许我们使用单个标识符(foo)来删除任意数量的绑定,并且我们不会影响该元素可能具有的任何其他mouseup或keyup绑定。

小提琴:http://jsfiddle.net/23H7J/41/

答案 1 :(得分:7)

很棒的答案!要将它们包装成一个函数,这里是一个基于当前答案的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);
});

Demo in fiddle

  

奖励:这样做的另一个好处是只需通过传递original handler to the off function来分离此特定功能的处理程序。否则,您将需要自定义命名空间。

另外,如果您希望处理程序在任何元素触发任何事件后立即触发一次,然后立即自行分离,则只需从中删除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
};

答案 2 :(得分:2)

您只需将$('input').off();添加到功能的末尾即可。

答案 3 :(得分:2)

要点火一次并继续射击,可以使用以下代码段:

https://jsfiddle.net/wo0r785t/1/

$.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似乎对以前的答案感到满意,但他的问题并未提及永久性的事件失效。

答案 4 :(得分:-1)

一次触发但继续触发后续更改的更简单方法是临时存储先前的值并进行快速比较:如果什么都没有更改,则不要运行该函数的其余部分。

jQUERY

$('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
});

请注意,我正在使用.on而不是.one

附加事件

PURE JAVASCRIPT

对于纯JavaScript解决方案,由于无法将多个事件传递给.addEventListener,因此需要单独添加侦听器。

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来检测可能的右键单击>粘贴,因为可以将鼠标释放到其他位置,而不必放到输入框中。为了安全起见,最好像我在上面的代码中所做的那样,使用keyuppasteinputchange