В jQuery, как прикрепить события к динамическим элементам HTML? [Дубликат]

450

Предположим, что у меня есть код 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" создается, когда пользователь нажимает на # anchor1.

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

Любая идея, как я могу это исправить?

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

  • 1
    Вот подробная статья о том, как связать событие клика для динамического элемента goo.gl/zlEbnv
  • 0
    Решение исключительно для javascript (vanilla js): stackoverflow.com/a/27373951/1385441
Показать ещё 1 комментарий
Теги:
events
dhtml

8 ответов

733
Лучший ответ

Я добавляю новый ответ, чтобы отразить изменения в более поздних версиях 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).

  • 0
    Похоже, у этого блестящего решения есть проблема с содержимым HTML, живущим в Fancybox. Я вернулся к созданию обработчиков для этого вручную. Я еще не пробовал iFrame Content, поэтому содержимое fanyxbos является частью тела или, в моем случае, переменной документа.
  • 5
    live () устарела и пришла .on (). Но не ясно, что когда я пишу $('selector').on('event', callback(){}) это не сработает. Нужно написать нужный селектор внутри на (). $(document).on('event', 'selector', callback(){}) или, $('body').on('event', 'selector', callback(){})
Показать ещё 6 комментариев
62

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

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

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

Привет,

  • 0
    Спасибо! Не удалось заставить его работать с другими ответами, ваше решение работало как чудо, однако, если я вызову RefreshSomeEventListener () после добавления динамического элемента, мое событие будет запущено дважды
  • 0
    @DKMudrechenko Вероятно, это потому, что вы не полностью удаляете слушателей событий из него.
36

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

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

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

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

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

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

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

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

  • 0
    Что если мой селектор должен быть родителем какого-то другого элемента? Например: $ ("p"). Parent (". Myclass"). Live ("click", ... Кажется, это не работает с live ().
  • 0
    Вы можете попытаться включить это в один запрос, такой как $ ("p: has (.myclass)"). Live ("click", ...). Примечание: в некоторых случаях live не работает для всех событий. Проверьте плагин livequery для поддержки, не предлагаемой live.
Показать ещё 1 комментарий
4

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

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

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

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

текст ссылки

$(function(){
    $(".myclass").live("click", function() {
        // do something
    });
});
  • 10
    live не рекомендуется.
2

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

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

1

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

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

1

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

Например:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню