привязать событие только один раз

Ответы:

190

Если вы можете применить его, возможно, вы захотите взглянуть на event.preventDefault и event.stopPropagation ИЛИ каждый раз отвязать и привязать в своем методе, например

function someMethod()
{
  $(obj).off('click').on('click', function(e) {
    // put your logic in here 
  });
}
pna
источник
19
Будьте осторожны, потому что это отключает ВСЕ события щелчка, и это не всегда желаемое поведение. Например, когда вы привязываете что-то к документу, вы хотите отвязать только это одно событие, а не все из них.
Мартиньш Бриедис
26
Если вы не хотите случайно отвязать другие события кликов, вы можете использовать function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
Ману
@Manu, который вы скопировали из этого ответа
aexl
89

В дополнение к ответу pna вы можете подумать об именовании своего события, чтобы случайно не отвязать все события щелчка.

function someMethod () {
    $ (obj) .unbind ('click.namespace'). bind ('click.namespace', function () {});
}

https://api.jquery.com/event.namespace/

Иэн
источник
10
Это должен быть принятый ответ. Отмена привязки всех событий щелчка может легко сломаться, особенно если это сложный проект с большим количеством jQuery. Спасибо за это! Не знал об этом простом решении с пространством имен !!
Simon Steinberger
С текущим jQuery это должно быть $(obj).off()и $(obj).on()соответственно. В противном случае использование пространства имен помогло, и это сработало. Спасибо!
aexl
19

Нет встроенного метода, чтобы определить, связали ли вы уже эту конкретную функцию. Вы можете привязать несколько функций щелчка к объекту. Например:

$('#id').bind('click', function(){
alert('hello');
});


$('#id').bind('click', function(){
alert('goodbuy');
});

если вы сделаете это при щелчке по объекту, он предупредит: "Привет, потом до свидания". Чтобы убедиться, что только одна функция привязана к событию щелчка, отвяжите обработчик события щелчка, затем привяжите желаемую функцию следующим образом:

$(obj).unbind('click').bind('click', function(){... });
Мэтт Пакстон
источник
12

Очевидное решение - не звонить someMethod()дважды. Если вы не можете это исправить, вы можете сохранить переменную состояния, чтобы она привязывалась только один раз, например:

function someMethod()
{
    if (!someMethod.bound) {
        $(obj).click(function() {});
        someMethod.bound = true;
    }
}

Примечание: здесь используется свойство самой функции, а не глобальная переменная, чтобы отслеживать, была ли она связана. Вы также можете использовать свойство для самого объекта.

Вы можете увидеть его работу здесь: http://jsfiddle.net/jfriend00/VHkxu/ .

jfriend00
источник
11

Или используйте функцию jQuery one (), которая похожа на on (), но запускает событие только один раз, даже если вы привязываете его несколько раз.

http://api.jquery.com/one/

xandrw
источник
8
Иногда помогает. но иногда вам нужно решение, в котором вы можете: ПРИСОЕДИНЯЙТЕСЬ ОДИН РАЗ, НО ИСПОЛЬЗУЙТЕ МНОГО.
Rzassar
5

jQuery позволяет довольно легко вызвать некоторые функции только один раз:

function someMethod()
{

     $(obj).click(function() {});
      this.someMethod = $.noop;
}
Esailija
источник
1
Это будет работать, только если someMethod является методом объекта или глобальной функции.
jcubic
jQuery.noopвсего на один символ короче function(){}, поэтому глупо говорить, что он «помогает» здесь, просто предоставляя пустую функцию. Вот пример этого общего решения без использования методов jQuery:var fn = function(){ fn = function(){}; do stuff; };
1j01
1
@ 1j01 Отредактировано для использования $вместо
Esailija
2

Это предложение, поскольку я не знаю вашей логики. Может или не может работать для вас.

Попробуйте объединить функции jquery live () и one (), и это даст лучший результат, чем повторные привязки событий.

Особые случаи работают, когда у вас есть 2 элемента DOM (родительский и дочерний). Live () на родительском узле гарантирует, что событие будет вызвано, а затем вызывает one () для динамической регистрации события, которое будет выполнено только один раз. (это обеспечивает аналогичные функции, такие как повторные привязки).

Бамбук
источник
One()функция работала, chromeно не работала safariв Mac.
Half Blood Prince
2

Вы можете добавить класс css к связанным элементам, а затем отфильтровать их:

function someMethod()
{
    $(obj).not('.click-binded')
          .click(function {})
          .addClass('click-binded');
}

Этот метод можно использовать также для плагинов:

  $(obj).not('.datetimepicker-applied')
        .datetimepicker()
        .addClass('datetimepicker-applied');
Бакыт Абдрасулов
источник
1
var bound = false;

function someMethod()
{
    if(!bound)
    {
       $(obj).click(function {});
       bound = true;
    }
}

но я, вероятно, изучил бы, почему он вызывается дважды, прежде чем найти какое-то обходное решение.

Кай Цин
источник
3
Если вы идете по этому пути, рассмотрите решение jfriend00, к которому boundприкреплено, someMethod()вместо того, чтобы загрязнять глобальное пространство имен.
nuala,
1

Если вы хотите выполнить привязку к объекту только один раз, вы должны реализовать флаг и придерживаться этого объекта.

Например:

if($('#id') && $('#id').data('done') == null)) {
    $('#id').bind('click', function() {
        alert('hello');
    });

    $('#id').data('done', true);
}
cscan
источник
1

Вы можете использовать эту функцию расширения jQuery.

$.fn.once = function (type, fn, uid) {
  if(uid == undefined) {
    console.error("Called $.once without uid\n", this, "\n", fn);
  }

  var dataStr = type+"-handler-"+uid;
  if(!this.data(dataStr)) {
    this.data(dataStr, true);
    this.on(type, fn);
  }
};

Вместо этого

$("button").on("click", function(){
  alert("You Clicked On A Button");
});

Ты делаешь это

$("button").once("click", function(){
  alert("You Clicked On A Button");
}, "btnHandler");

Теперь, когда у меня есть функция вокруг него

function addBtnHandler() {
  $("button").once("click", function() {
    alert("You Clicked On A Button");
  }, "btnHandler");
}

И я называю это несколько раз

addBtnHandler();
addBtnHandler();
addBtnHandler();

Он делает это только один раз.

Обратите внимание, что расширение работает, проверяя как uid, так и тип. Это означает, что вы можете связывать разные типы обработчиков с одним и тем же uid, вы можете этого захотеть, а можете и не захотеть. Чтобы изменить его, отредактируйте.

var dataStr = type+"-handler-"+uid;

Что-то вроде

var dataStr = "handler-"+uid;

Натнольт
источник
1

Я также пытался использовать off и on метод jquery для привязки события только один раз с элементом dom, который еще не существует, или элемент dom еще не создан.

$('.select').off('event').on('event', 'selector', function(e){ // });

Этот код не работал должным образом

Я наткнулся на очень прибыльный метод - «один». Это очень полезно, если вы хотите привязать событие только один раз.

Вы можете найти документ здесь http://api.jquery.com/one/

Это то же самое, что и метод on, но отличается своим поведением: не следует придерживаться события для нескольких селекторов.

$('body').one('click', 'selector', function(){ // do your stuff here });
Анкит Вишвакарма
источник
1

Вы можете добиться этого с чистым JS, используя addEventListener метод и его один раз вариант

target.addEventListener('click', handler, {once: true});
Скав
источник
2
Это приводит к тому, что событие становится несвязанным после однократного щелчка по элементу. Это не решает проблему многократной привязки событий.
Top Cat