Как прикрепить события к динамическим HTML-элементам с помощью jQuery?

Предположим, у меня есть код jQuery, который присоединяет обработчик событий ко всем элементам с классом .myclass.

Например:

$(function(){
    $(".myclass").click( function() {
        // do something
    });
});

И мой HTML может быть таким:

<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>

Это работает без проблем. Однако подумайте, не были ли элементы .myclass записаны на страницу когда-нибудь в будущем.

Например:

<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
    $("#anchor1").click( function() {
        $("#anchor1").append('<a class="myclass" href="#">test4</a>');
    });
});
</script>

В этом случае ссылка test4 создается, когда пользователь нажимает a#anchor1.

Ссылка test4 не имеет связанного с ней обработчика click(), хотя у нее есть class="myclass".

По сути, я хотел бы написать обработчик click() один раз и применить его как к контенту, присутствующему при загрузке страницы, так и к контенту, добавленному позже через AJAX / DHTML. Есть идеи, как я могу это исправить?


person frankadelic    schedule 31.08.2009    source источник
comment
Подробная статья о том, как привязать событие клика к динамическому элементу goo.gl/zlEbnv   -  person Satinder singh    schedule 17.08.2015
comment
Решение только на чистом javascript (vanilla js): stackoverflow.com/a/27373951/1385441   -  person Ram Patra    schedule 18.04.2016
comment
Вот ответ youtube.com/watch?v=unk-U_LQWuA.   -  person Prem    schedule 09.10.2016


Ответы (8)


Я добавляю новый ответ, чтобы отразить изменения в более поздних выпусках jQuery. Метод .live () устарел с jQuery 1.7.

С http://api.jquery.com/live/

Начиная с jQuery 1.7, метод .live () устарел. Используйте .on () для присоединения обработчиков событий. Пользователи более старых версий jQuery должны использовать .delegate () вместо .live ().

Для jQuery 1.7+ вы можете прикрепить обработчик событий к родительскому элементу с помощью .on () и передать селектор a в сочетании с myclass в качестве аргумента.

См. http://api.jquery.com/on/.

Так что вместо ...

$(".myclass").click( function() {
    // do something
});

Ты можешь написать...

$('body').on('click', 'a.myclass', function() {
    // do something
});

Это будет работать для всех тегов с 'myclass' в теле, уже присутствующих или динамически добавленных позже.

Тег body используется здесь, поскольку в примере не было более близкого статического окружающего тега, но любой родительский тег, существующий при вызове метода .on, будет работать. Например, тег ul для списка, в который будут добавлены динамические элементы, будет выглядеть так:

$('ul').on('click', 'li', function() {
    alert( $(this).text() );
});

Пока существует тег ul, это будет работать (элементы li еще не нужны).

person Sean    schedule 17.02.2012
comment
У этого блестящего решения, похоже, есть проблема с HTML-содержимым, живущим в Fancybox. Я вернулся к созданию обработчиков для этого вручную. Я еще не пробовал iFrame Content, поэтому содержимое fanyxbos является частью тела или, в моем случае, переменной документа. - person ; 11.08.2013
comment
live () устарел, и появился .on (). Но непонятно, когда я напишу $('selector').on('event', callback(){}), это не сработает. Нужно написать желаемый селектор внутри (). $(document).on('event', 'selector', callback(){}) или, $('body').on('event', 'selector', callback(){}) - person Satya Prakash; 21.12.2013
comment
как насчет производительности? это то же самое, что напрямую прикреплять события? - person Juan; 29.04.2014
comment
Не работает, если <a> элемент имеет href адрес, равный http://???? - person Mostafa; 04.07.2016
comment
$('body').on('each', 'myclass', function() { // do something }); @Sean Я пытался что-то сделать для каждого класса, но это не сработало. Что случилось? - person horse; 03.09.2016
comment
в моем случае вместо этого он назначает событие родительскому тегу. Я использую jquery версии 1.12.4. Любая идея? - person Yusril Maulidan Raji; 19.06.2017
comment
Отличное решение, хорошо работает при добавлении элементов DOM через javascript, которые были добавлены во время document.ready. - person Sanjok Gurung; 16.08.2018
comment
@ Шон и Чак, спасибо за ответ и редактирование соответственно. :) - person Vibhav Chaddha; 24.12.2018
comment
$ ('. yourDynamicElement'). attr ('onClick', 'yourFunction ()'); также будет работать должным образом - person Aditya; 18.10.2020

Иногда этого (ответ, получивший наибольшее количество голосов) не всегда достаточно:

$('body').on('click', 'a.myclass', function() {
    // do something
});

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

Например:

function RefreshSomeEventListener() {
    // Remove handler from existing elements
    $("#wrapper .specific-selector").off(); 

    // Re-add event handler for all matching elements
    $("#wrapper .specific-selector").on("click", function() {
        // Handle event.
    }
}

Поскольку это функция, всякий раз, когда я настраиваю свой слушатель таким образом, я обычно вызываю ее, когда документ готов:

$(document).ready(function() {
    // Other ready commands / code

    // Call our function to setup initial listening
    RefreshSomeEventListener();
});

Затем, когда вы добавляете какой-либо динамически добавляемый элемент, снова вызывайте этот метод:

function SomeMethodThatAddsElement() {
    // Some code / AJAX / whatever.. Adding element dynamically

    // Refresh our listener, so the new element is taken into account
    RefreshSomeEventListener();
}

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

С уважением,

person Chandler Zwolle    schedule 15.07.2014
comment
Спасибо! Не удалось заставить его работать с другими ответами, ваше решение работало как шарм, однако, если я вызываю RefreshSomeEventListener () после добавления динамического элемента, мое событие запускается дважды - person DKMudrechenko; 23.03.2015
comment
@DKMudrechenko Скорее всего, это потому, что вы не полностью удаляете из него прослушиватели событий. - person Ryan Steffer; 12.04.2017
comment
Это работает, и это тоже хорошее объяснение. - person John Ruiz; 26.02.2021

После jQuery 1.7 предпочтительными методами являются .on () и . off ()

Ответ Шона показывает пример.

Устарело:

Используйте функции jQuery .live() и _ 2_. Доступно в jQuery 1.3.x

Из документов:

Чтобы отображать текст каждого абзаца в окне предупреждения при каждом щелчке:

$("p").live("click", function(){
  alert( $(this).text() );
});

Кроме того, плагин livequery делает это и поддерживает большее количество событий.

person Matt Brunell    schedule 31.08.2009
comment
Что, если мой селектор должен быть родительским для какого-то другого элемента? Например: $ (p) .parent (.myclass) .live (щелкните, ... Похоже, это не работает с live (). - person frankadelic; 01.09.2009
comment
Вы можете попытаться включить это в один запрос, например $ (p: has (.myclass)). Live (click, ...). Примечание: в некоторых случаях live работает не для всех мероприятий. Ознакомьтесь с плагином livequery для получения поддержки, не предлагаемой live. - person Matt Brunell; 01.09.2009
comment
Это уже не правильный ответ. Метод .live () устарел с jQuery 1.7. Вместо этого используйте .on(). Давайте получим правильный ответ [stackoverflow.com/a/9331127/363701] несколько голосов. Или @Matt - вы хотите обновить свой ответ? - person Zach Lysobey; 17.02.2012

Если вы добавляете к DOM кучу якорей, лучше изучите делегирование событий.

Вот простой пример:

$('#somecontainer').click(function(e) {   
  var $target = $(e.target);   
  if ($target.hasClass("myclass")) {
    // do something
  }
});
person ScottE    schedule 31.08.2009

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

$(document).bind('click', function (e) {
   var target = $(e.target);
   if (target.is('.myclass')) {
      e.preventDefault(); // if you want to cancel the event flow
      // do something
   } else if (target.is('.myotherclass')) {
      e.preventDefault();
      // do something else
   }
});

Пользуюсь им какое-то время. Работает как шарм.

В jQuery 1.7 и новее рекомендуется использовать .on() вместо привязки или любого другого метода делегирования событий, но .bind() по-прежнему работает.

person i--    schedule 29.03.2013

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

текст ссылки

$(function(){
    $(".myclass").live("click", function() {
        // do something
    });
});
person andres descalzo    schedule 31.08.2009
comment
live устарел. - person Francisco Corrales Morales; 13.05.2014

Если вы используете jQuery 1.3+, используйте. live ()

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

person redsquare    schedule 31.08.2009

Вы хотите использовать функцию live(). См. документы.

Например:

$("#anchor1").live("click", function() {
    $("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
person Adam Bellaire    schedule 31.08.2009
comment
live устарел. - person Nardong Bagsik; 13.01.2020