Найкращий спосіб видалити обробник подій в 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

Після цього обидва події клацання будуть звільнені.

Як люди заявляли, ви можете скористатися відключенням, щоб видалити всі події натискання:

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

Якщо ви хочете додати одну подію, а потім видалити її (не видаляючи інших, які могли бути додані), тоді ви можете скористатися простором імен подій:

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

і видалити лише вашу подію:

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

6
Чи є спосіб перевірити, чи unbind()працює? Я додав це, і обидві події ще тривають.
Девід Йелл

19
Добре, якщо обидві події все ще стартують, тоді, очевидно, це не працює. Вам потрібно буде дати більше інформації, щоб отримати правильну відповідь. Спробуйте задати окреме запитання.
samjudson

13
Стара відповідь - так само, як включена інформація про простір імен - але я забуваю; повертає або вимикає об'єкт jQ? Якщо так, можливо, більш повною відповіддю буде ланцюжок $('#myimage').off('click').on('click',function(){...})
ромашок

3
Так, так, так, якщо так, якщо ви хочете очистити всі інші події клацання, а потім додати свої власні, ви могли б зробити вищезазначений ланцюжок дзвінка.
samjudson

Використання .unbind()допомогло мені в ситуації, коли я перемикав купу прапорців, але я повторно додав .click()обробник повторно, викликаючи зависання програми.
TecBrat

63

Ця функція була недоступною, коли відповіли на це запитання, але ви також можете використовувати метод live () для вмикання / відключення подій.

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

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

Що станеться з цим кодом, це те, що при натисканні кнопки #mydisablebutton він додасть клас відключений до елемента #myimage. Це зробить так, що селектор більше не відповідає елементу, і подія не буде запущена, поки не буде видалено клас "інвалід", що робить селектор .live () знову дійсним.

Це має й інші переваги, додаючи також стиль на основі цього класу.


3
Хороший спосіб використання live(), ніколи не думав про використання цього способу раніше ... Окрім зручності кодування, це швидше чи він пропонує якісь інші переваги щодо використання bind / unbind?
чакрит

2
Якщо ви додаєте / видаляєте елементи, то існують певні переваги в роботі над bind, оскільки зв'язування з live виконуваться лише один раз. jQuery, здається, рухається до більшої кількості трансляцій та делегує події, а не прив'язується до конкретних елементів.
MacAnthony

3
Щоб вимкнути трансляцію, ви можете скористатися die ()
Місяць

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

Використовуючи argument.callee , ми можемо забезпечити видалення одного конкретного обробника анонімних функцій і, таким чином, мати єдиний обробник часу для даної події. Сподіваюся, що це допомагає іншим.


2
Абсолютно, хоча іноді ви можете мати певну логіку щодо того, коли обробник повинен бути незв'язаним (наприклад, не скасовувати, якщо вони спочатку не подали текстове поле).
ghayes

5
ARG.callee знеструмлено в суворому режимі!
zloctb

37

Це можна зробити за допомогою функції відв’язування.

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

Ви можете додати декілька обробників подій до одного об’єкта та події в jquery. Це означає, що додавання нового не замінює старі.

Існує кілька стратегій зміни обробників подій, наприклад, простори імен подій. Про це є кілька сторінок в онлайн-документах.

Подивіться на це питання (саме так я дізнався про розв’язування). У відповідях є корисний опис цих стратегій.

Як читати зв'язані функції зворотного виклику в jquery



30

Мені довелося встановити подію на нуль за допомогою опори та attr. Я не міг зробити це з тим чи іншим. Я також не міг дістати .незалежно працювати. Я працюю над елементом TD.

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

1
Я проголосував за це, тому що я намагався відв'язати онблур близько 30 хвилин. '.unbind' не працювало, '.prop' не працювало, '.attr' не працювало, але ця хитрість і з .prop і .attr разом зробила трюк. дивно. Я використовую Chrome з jquery 1.7.2
Джеремі

Те ж саме! я намагався видалити подію натискання з простого тега <a>! Дякую за це. У моєму випадку .prop ("onclick", null) було достатньо.
Ян Лобау

те ж саме. unbind and 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

Всі описані підходи для мене не працювали, тому що я додавав подію клацання on()в документ, де елемент був створений під час виконання:

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


Моє вирішення:

Оскільки я не міг розв'язати клас ".button", я просто призначив ще один клас кнопці, яка мала ті ж стилі CSS. Роблячи це, обробник наживо / на подію остаточно проігнорував натискання:

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