Лучший способ удалить обработчик событий в jQuery?

874

У меня есть input type="image". Это действует как заметки ячейки в Microsoft Excel. Если кто-то вводит число в текстовое поле, с которым сопряжен этот input-image, я настраиваю обработчик событий для input-image. Затем, когда пользователь нажимает кнопку image, они получают небольшое всплывающее окно, чтобы добавить некоторые примечания к данным.

Моя проблема в том, что когда пользователь вводит нуль в текстовое поле, мне нужно отключить обработчик события input-image. Я пробовал следующее, но безрезультатно.

$('#myimage').click(function { return false; });
Теги:
input

17 ответов

1362
Лучший ответ

jQuery ≥ 1.7

С обновлением jQuery 1.7 API-интерфейс событий был обновлен, .bind()/.unbind() по-прежнему доступны для обратной совместимости, но предпочтительный метод использует on()/off(). Теперь будет ниже:

$('#myimage').click(function() { return false; }); // Adds another click event
$('#myimage').off('click');
$('#myimage').on('click.mynamespace', function() { /* Do stuff */ });
$('#myimage').off('click.mynamespace');

jQuery < 1.7

В вашем примере кода вы просто добавляете другое изображение клика, а не переопределяете предыдущий:

$('#myimage').click(function() { return false; }); // Adds another click event

Затем будут запущены оба события щелчка.

Как говорили люди, вы можете использовать unbind для удаления всех событий click:

$('#myimage').unbind('click');

Если вы хотите добавить одно событие, а затем удалить его (без удаления каких-либо других, которые могли быть добавлены), вы можете использовать пространство имен событий:

$('#myimage').bind('click.mynamespace', function() { /* Do stuff */ });

и удалить только ваше событие:

$('#myimage').unbind('click.mynamespace');
  • 4
    Есть ли способ проверить, работает ли unbind() ? Я добавил это, и оба события все еще стреляют.
  • 18
    Хорошо, если оба события все еще стреляют, тогда очевидно, что это не работает. Вы должны дать больше информации, чтобы получить правильный ответ. Попробуйте задать отдельный вопрос.
Показать ещё 11 комментариев
54

Это не было доступно, когда на этот вопрос был дан ответ, но вы также можете использовать метод live() для включения/отключения событий.

$('#myimage:not(.disabled)').live('click', myclickevent);

$('#mydisablebutton').click( function () { $('#myimage').addClass('disabled'); });

Что произойдет с этим кодом, так это то, что при нажатии кнопки #mydisablebutton он добавит класс, отключенный к элементу #myimage. Это приведет к тому, что селектор больше не будет соответствовать элементу, и событие не будет запущено до тех пор, пока не будет удален класс "disabled", снова сделав селектор .live() действительным.

У этого есть другие преимущества, добавляя стиль на основе этого класса.

  • 2
    Хороший способ использовать live() , никогда раньше не задумывался об использовании его таким образом ... Помимо удобства написания кода, это быстрее или предлагает какие-то другие преимущества использования bind / unbind?
  • 1
    Если вы добавляете / удаляете элементы, то у bind есть определенные преимущества в производительности по сравнению с bind, поскольку связывание с live выполняется только один раз. Кажется, jQuery движется к более активным и делегирующим событиям, а не к конкретным элементам.
Показать ещё 3 комментария
34

Это можно сделать, используя функцию unbind.

$('#myimage').unbind('click');

Вы можете добавить несколько обработчиков событий к одному объекту и событию в jquery. Это означает, что добавление нового не заменяет старые.

Существует несколько стратегий для изменения обработчиков событий, таких как пространства имен событий. В онлайн-документах есть несколько страниц об этом.

Посмотрите на этот вопрос (что я узнал о unbind). В ответах есть несколько полезных описаний этих стратегий.

Как читать функции обратного вызова связанного наведения в jquery

33

Если вы хотите ответить на событие всего на один раз, следующий синтаксис должен быть действительно полезным:

 $('.myLink').bind('click', function() {
   //do some things

   $(this).unbind('click', arguments.callee); //unbind *just this handler*
 });

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

  • 11
    Для этого jQuery уже имеет jQuery#one('click', fn) .
  • 2
    Абсолютно, хотя иногда вам может потребоваться определенная логика относительно того, когда обработчик должен быть не связан (например, не отменять привязку, если они сначала не отправили текстовое поле).
Показать ещё 1 комментарий
29

Мне нужно было установить событие null с помощью prop и attr. Я не мог сделать это с тем или другим. Я тоже не мог работать. Я работаю над элементом TD.

.prop("onclick", null).attr("onclick", null)
  • 1
    Я проголосовал за это, потому что я пытался развязать onblur в течение приблизительно 30 минут. «.unbind» не работал, «.prop» не работал, «.attr» не работал, но этот трюк с обоими .prop и .attr вместе делал свое дело. странный. Я использую Chrome с JQuery 1.7.2
  • 0
    Тоже самое! я пытался удалить событие click из простого тега <a>! Спасибо за это. В моем случае было достаточно .prop ("onclick", null).
Показать ещё 4 комментария
29

возможно, метод unbind будет работать для вас

$("#myimage").unbind("click");
9

Обновлено для 2014

Используя последнюю версию jQuery, вы теперь можете отменить все события в пространстве имен, просто сделав $( "#foo" ).off( ".myNamespace" );

9

Вы можете добавить обработчик onclick как встроенную разметку:

<input id="addreport" type="button" value="Add New Report" onclick="openAdd()" />

Если да, то jquery .off() или .unbind() не будет работать. Вы также должны добавить исходный обработчик событий в jquery:

$("#addreport").on("click", "", function (e) {
   openAdd();
});

Затем jquery имеет ссылку на обработчик события и может удалить его:

$("#addreport").off("click")

VoidKing упоминает это чуть более наклонно в комментарии выше.

9

Если событие привязано таким образом, и цель должна быть не привязана:

$('#container').on('click','span',function(eo){
    alert(1);

    $(this).off(); //seams easy, but does not work

    $('#container').off('click','span'); //clears click event for every span

    $(this).on("click",function(){return false;}); //this works.

});​
6

Спасибо за информацию. очень полезно, я использовал его для блокировки взаимодействия страниц в режиме редактирования другим пользователем. Я использовал его в сочетании с ajaxComplete. Не обязательно такое же поведение, но несколько похожее.

function userPageLock(){
    $("body").bind("ajaxComplete.lockpage", function(){
        $("body").unbind("ajaxComplete.lockpage");
        executePageLock();      
    });
};  

function executePageLock(){
    //do something
}
5

Лучший способ удалить встроенное событие onclick - $(element).prop('onclick', null);

2

В случае, когда метод .on() ранее использовался с конкретным селектором, как в следующем примере:

$('body').on('click', '.dynamicTarget', function () {
    // Code goes here
});

Оба метода unbind() и .off() не будут работать.

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

$("body").undelegate(".dynamicTarget", "click")
  • 1
    Я прокручивал всю страницу, пока искал это решение, работал как шарм.
2

если вы установите onclick через html, вам нужно removeAttr ($(this).removeAttr('onclick'))

если вы установите его через jquery (как после первого щелчка в моих примерах выше), вам нужно unbind($(this).unbind('click'))

2

Это также отлично работает. Простое и удобное. http://jsfiddle.net/uZc8w/570/

$('#myimage').removeAttr("click");
1

Я знаю, что это происходит поздно, но почему бы не использовать простой JS для удаления события?

var myElement = document.getElementByID("your_ID");
myElement.onclick = null;

или, если вы используете именованную функцию как обработчик события:

function eh(event){...}
var myElement = document.getElementByID("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it
1

Надеюсь, что мой нижний код объясняет все. HTML:

(function($){

     $("#btn_add").on("click",function(){
       $("#btn_click").on("click",added_handler);
       alert("Added new handler to button 1");
     });

  
 
     $("#btn_remove").on("click",function(){
       $("#btn_click").off("click",added_handler);
       alert("Removed new handler to button 1");
     });

  
   function fixed_handler(){
    alert("Fixed handler");
  }
  
   function added_handler(){
    alert("new handler");
  }
  
  $("#btn_click").on("click",fixed_handler);
  $("#btn_fixed").on("click",fixed_handler);
  
  
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn_click">Button 1</button>
  <button id="btn_add">Add Handler</button>
  <button id="btn_remove">Remove Handler</button>
  <button id="btn_fixed">Fixed Handler</button>
  • 1
    почему вы входите })(jQuery); в IIFE, когда он уже доступен глобально?
  • 2
    Хороший вопрос, Брайан. Этот метод был введен в мой ген из-за практики. - Может быть некоторая возможность для плагина не jquery иметь переменную $, поэтому я не могу использовать $ напрямую. - Частое использование слова "jQuery" в файле сценария js может увеличить размер файла в байтах, где jQuery - это 6-байтовая строка. Поэтому я предпочитаю использовать «$» или любую переменную из одного байта.
0

Все описанные подходы не работали для меня, потому что я добавлял событие click с on() в документ, где элемент был создан во время выполнения:

$(document).on("click", ".button", function() {
    doSomething();
});


Мое обходное решение:

Поскольку я не мог отвязать класс ".button", я просто назначил другой класс кнопке с теми же стилями CSS. Посредством этого обработчик live/on-event проигнорировал щелчок наконец:

// prevent another click on the button by assigning another class
$(".button").attr("class","buttonOff");

Надеюсь, что это поможет.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню