Как мне прикрепить события к динамическим 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. Любая идея, как я могу это исправить?

Ответ 1

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

Из http://api.jquery.com/live/

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

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

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

Итак, вместо...

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

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

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

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

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

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

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

Ответ 2

Иногда выполнение этого (ответ на верхний голос) не всегда достаточно:

$('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();
}

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

Привет,

Ответ 3

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

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

Теперь устарела:

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

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

текст ссылки

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

Ответ 6

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

$(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() все еще работает.

Ответ 7

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

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

Ответ 8

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

Например:

$("#anchor1").live("click", function() {
    $("#anchor1").append('<a class="myclass" href="#">test4</a>');
});