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

1053

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

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

$('#myimage').click(function { return false; });
Рэнди Л
источник

Ответы:

1626

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 для удаления всех событий кликов:

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

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

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

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

$('#myimage').unbind('click.mynamespace');
samjudson
источник
6
Есть ли способ проверить, unbind()работает ли? Я добавил это, и оба события все еще стреляют.
Дэвид Йелл
19
Хорошо, если оба события все еще стреляют, тогда очевидно, что это не работает. Вы должны дать больше информации, чтобы получить правильный ответ. Попробуйте задать отдельный вопрос.
Самюдсон
13
Старый ответ - также как включенная информация о пространстве имен - но я забыл; вкл / выкл возвращает объект jQ? Если это так, возможно, более полный ответ был бы на цепочку $('#myimage').off('click').on('click',function(){...})
гирлянд
3
Да, да, если да, если вы хотите очистить все остальные события кликов, а затем добавить свои, вы можете выполнить вышеуказанный цепной вызов.
Самджудсон
Использование .unbind()помогло мне в ситуации, когда я включал несколько флажков, но изменил размер, я .click()неоднократно повторно добавлял обработчик, вызывая зависание приложения.
TecBrat
63

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

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

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

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

Это имеет и другие преимущества, добавляя стилизацию на основе этого класса.

MacAnthony
источник
3
Хороший способ использования live(), никогда не задумывался об использовании этого способа раньше ... Помимо удобства программирования, это быстрее или предлагает какие-то другие преимущества использования bind / unbind?
чакрит
2
Если вы добавляете / удаляете элементы, то у bind есть определенные преимущества в производительности по сравнению с bind, поскольку связывание с live выполняется только один раз. Кажется, что jQuery движется к более активным и делегирующим событиям, а не к определенным элементам.
MacAnthony
3
Чтобы отключить live, вы можете использовать die ()
Moons
9
"Начиная с jQuery 1.7, метод .live () устарел. Используйте .on () для присоединения обработчиков событий. Пользователи более старых версий jQuery должны использовать .delegate () вместо предпочтения .live ()." api.jquery.com/live
Лукас Поттерский
12
Ах, непостоянный jQuery, однажды вы приносите 300 повторений одному парню, а на следующий день он устарел.
MrBoJangles
37

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

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

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

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

ghayes
источник
2
Абсолютно, хотя иногда вам может потребоваться определенная логика относительно того, когда обработчик должен быть свободен (например, не отменять привязку, если они сначала не отправили текстовое поле).
Ghayes
5
arguments.callee развращается в строгом режиме!
zloctb
37

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

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

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

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

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

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

Mnebuerquo
источник
32

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

$("#myimage").unbind("click");
Джон Бокер
источник
30

Я должен был установить событие равным нулю, используя опору и атрибут. Я не мог сделать это с одним или другим. Я также не мог заставить .unbind работать. Я работаю над элементом TD.

.prop("onclick", null).attr("onclick", null)
dwhittenburg
источник
1
Я проголосовал за это, потому что я пытался развязать onblur около 30 минут. «.unbind» не работал, «.prop» не работал, «.attr» не работал, но этот трюк с обоими .prop и .attr вместе делал свое дело. странный. Я использую Chrome с jquery 1.7.2
Джереми
Тоже самое! я пытался удалить событие click из простого тега <a>! Спасибо за это. В моем случае .prop ("onclick", null) было достаточно.
Ян Лобау
тоже самое. unbind и off не работали для меня на FF с jq 1.7.2 и .prop ("onclick", null) также было достаточно в моем случае
bryanallott
4
Я думаю, что вышеописанные методы не сработали для вас, ребята, из-за того, как вы их настроили. Если вы записали обработчик событий в DOM, то да, очистка этого атрибута необходима для очистки обработчика событий, однако, я думаю, что большинство людей (включая меня) хотят сохранить такие вещи (javascrip, обработчики событий и т. Д.) Вне DOM, поэтому, когда мы хотим настроить обработчик событий, мы используем что-то вроде $("#elementId").click(function(){//Event execution code goes here});этого, чтобы его вообще не было на html-странице. Чтобы понять, что нам на самом деле нужно использовать .unbind(), или предпочитаемое.off()
VoidKing
Вот пример того, кто только что потратил час, чтобы обнаружить, что свойства, добавленные через jQuery, не отображаются на панели элементов Chrome. Я пытался, unbindи offэто не решало проблему. Большое спасибо!
Ренан
13

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

$('#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.

});​

источник
11

Вы можете добавлять 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 упоминает это немного более косвенно в комментарии выше.

davaus
источник
9

Обновлено на 2014

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

alexpls
источник
8

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

Шахрух Азим
источник
8

Для remove ВСЕХ event-handlers это то, что работало для меня:

Удалить все обработчики событий - значит иметь простой объект HTML structureбез event handlersпривязки к нему elementи его child nodes. Для этого jQuery's clone()помогло.

var original, clone;
// element with id my-div and its child nodes have some event-handlers
original = $('#my-div');
clone = original.clone();
//
original.replaceWith(clone);

С этим у нас будет cloneместо originalбез event-handlersна этом.

Удачи...

Акаша
источник
7

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

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

function executePageLock(){
    //do something
}
jquery_user
источник
5

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

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

Оба unbind()и .off()методы не являются собираются работать.

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

$("body").undelegate(".dynamicTarget", "click")
Илья Ростовцев
источник
1
Я прокручивал всю страницу, пока искал это решение, работал как шарм.
Абхишек Пандей
4

Если вы используете $(document).on()для добавления слушателя к динамически созданному элементу, вам, возможно, придется использовать следующее, чтобы удалить его:

// add the listener
$(document).on('click','.element',function(){
    // stuff
});

// remove the listener
$(document).off("click", ".element");
ow3n
источник
2

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

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

Ишан Лиянаге
источник
2

Я знаю, что это поздно, но почему бы не использовать обычный 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
Сильвиу Преда
источник
Хорошее предложение, я предпочитаю использовать нативный javascript, когда он будет доступен
Michiel
1

Все описанные подходы не сработали для меня, потому что я добавлял событие 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");

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

Кай Ноак
источник
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>

mysticmo
источник
1
почему вы })(jQuery);входите в IIFE, когда к нему уже можно получить доступ по всему миру?
Брайан Р
2
Хороший вопрос, Брайан. Этот метод был введен в мой ген из-за практики. - Может быть некоторая возможность для плагина не jquery иметь переменную $, поэтому я не могу использовать $ напрямую. - Частое использование слова «jQuery» в файле сценария js может увеличить размер файла в байтах, где jQuery - это 6-байтовая строка. Поэтому я предпочитаю использовать «$» или любую переменную из одного байта.
Мистикмо
0

Просто удалите это из кнопки:

$('.classname').click(function(){
$( ".classname" ).remove();
});
Митра
источник