Лучший способ удалить обработчик событий в 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');

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 () действительным.

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


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 , мы можем гарантировать, что один конкретный обработчик анонимной функции будет удален, и, таким образом, иметь один обработчик времени для данного события. Надеюсь, что это помогает другим.


2
Абсолютно, хотя иногда вам может потребоваться определенная логика относительно того, когда обработчик должен быть свободен (например, не отменять привязку, если они сначала не отправили текстовое поле).
— Ghayes

5
arguments.callee развращается в строгом режиме!
— zloctb

37

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

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

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

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

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

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



30

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

.prop("onclick", null).attr("onclick", null)

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


9

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

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



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
}

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


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>


1
почему вы })(jQuery);входите в IIFE, когда к нему уже можно получить доступ по всему миру?
— Брайан Р

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

0

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

$('.classname').click(function(){
$( ".classname" ).remove();
});
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.