Удалить делегированный обработчик событий jQuery для определенного объекта

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

HTML:

<button>One</button>
<button>Two</button>
<button>Three</button>

JS:

$(document).on('click', 'button', function(ev) {
    // doesn't work because argument needs to be a string
    $(document).off('click', $(ev.target));

    // doesn't do what I want b/c turns off events on all buttons, not just this one
    $(document).off('click', 'button');

    // doesn't work because event is on document, not button
    $(ev.target).off('click');
});

off документация говорит, что мне нужно предоставить строку в качестве второго аргумента, не объект jQuery ($(ev.target)), но если я укажу строку, не будет значения, относящегося только к элементу, по которому щелкнули.

Из документации по jQuery:

Чтобы удалить определенные делегированные обработчики событий, укажите аргумент селектора. Строка селектора должна точно совпадать с той, что была передана в .on() при подключении обработчика событий. Чтобы удалить все делегированные события из элемента, не удаляя неделегированные события, используйте специальное значение «**».

Так как же отключить делегированный обработчик событий для определенного элемента?

Вот JSFiddle приведенного выше кода

ОБНОВЛЕНИЕ: добавлено несколько примеров вариантов, которые не работают на основе первоначальных ответов.


person MegaMatt    schedule 28.05.2015    source источник
comment
Нет, потому что это удалит все делегированные обработчики событий из всех кнопок. Я просто хочу удалить его из того, по которому щелкнули.   -  person MegaMatt    schedule 28.05.2015
comment
В качестве обходного пути может быть полезно: есть ли способ делегировать событие в jQuery?   -  person showdev    schedule 28.05.2015
comment
Вы пробовали ev.target в качестве второго аргумента?   -  person lshettyl    schedule 28.05.2015
comment
@LShetty Кажется, не работает.   -  person showdev    schedule 28.05.2015


Ответы (3)


Прочитав в Интернете, ответ - вы не можете! Вы можете удалить все или ничего. Обходной путь может быть примерно следующим.

$(document).on('click', '.btn', function (ev) {
    alert('pressed');
    $(this).removeClass("btn");
});

Demo@Fiddle

Пример HTML:

<button class="btn">One</button>
<button class="btn">Two</button>
<button class="btn">Three</button>
person lshettyl    schedule 28.05.2015
comment
Так что этот ответ будет работать для меня, но только потому, что мои обстоятельства таковы, что мне нужно, чтобы событие сработало только один раз. Тем не менее, я могу видеть другие случаи, когда вам нужно удалить делегированное событие для определенного элемента на основе некоторой условной логики, которая может быть неверной при первом запуске события. По этой причине я хотел бы увидеть способ сделать это. - person MegaMatt; 28.05.2015
comment
В свете моего комментария выше, мне кажется, что единственный обработчик событий в самом документе — это всего лишь один обработчик событий, даже если он распространяется на другие элементы. Если вы посмотрите на это с этой точки зрения, не кажется логичным удалять обработчики из его дочерних элементов, потому что они все равно не существуют. Вы бы либо все удалили, либо вообще ничего. - person MegaMatt; 28.05.2015
comment
Этот ответ, кажется, дает много информации об этой проблеме codereview.stackexchange.com/questions/16466/ - person Zack; 28.05.2015

В дополнение к тому, что сказал lshettyl (текущий верхний пост), дополнительная работа заключается в том, чтобы привязать новый прослушиватель событий непосредственно к элементу, который вы пытаетесь удалить, и вызвать в нем stopPropagation().

Это предотвратит перемещение события вверх по DOM и достижение обработчика событий, изначально привязанного к документу. Также это позволит вам сохранить некоторые функции при нажатии кнопки, например, предупреждение пользователю о том, что эта кнопка уже была нажата, или что-то в этом роде.

$(document).on('click', 'button', function(ev) {
    // Your logic to occur on button click

    // Prevent further click on just this button
    $(this).click(function(event) {
        event.stopPropagation();
    }):
});
person kjb085    schedule 01.05.2017
comment
stopImmediatePropogation() пригодится, когда вы хотите предотвратить срабатывание последующих слушателей. - person Faizaan Gagan; 16.03.2021

Вопрос: Обязательно ли использовать делегированные события? Как сказал LShetty, невозможно удалить делегированное событие для одного элемента. Вы либо удаляете всю делегацию события, либо оставляете ее. Вместо этого вы можете попробовать использовать другой селектор, как в этом примере.

$('button').on('click', function(ev) {
    $('#output').append('Clicked! ');
    $(this).off('click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<button>One</button>
<button>Two</button>
<button>Three</button>
<div id="output"></div>

person Zack    schedule 28.05.2015
comment
Да, это нужно делегировать, потому что эти элементы будут появляться и исчезать со страницы. Это динамическое веб-приложение. - person MegaMatt; 28.05.2015
comment
В этом случае лучшим решением, вероятно, будет что-то вроде решения LShetty, в котором вы добавляете/удаляете класс для элементов после их щелчка, поэтому делегированное событие больше не применяется к этим элементам. - person Zack; 28.05.2015
comment
Да, это действительно кажется лучшим решением. - person MegaMatt; 28.05.2015