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


104

У меня такой код:

function someMethod()
{
  $(obj).click(function {});
}

someMethod вызывается дважды, поэтому событие щелчка связывается дважды. Как сделать привязку только один раз?


Ответы:


190

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

function someMethod()
{
  $(obj).off('click').on('click', function(e) {
    // put your logic in here 
  });
}

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/ .


11

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

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


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

5

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

function someMethod()
{

     $(obj).click(function() {});
      this.someMethod = $.noop;
}

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);
}

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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.