Событие клика не работает с динамически сгенерированными элементами

339
<html>
<head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">

        $(document).ready(function() {

            $("button").click(function() {
                $("h2").html("<p class='test'>click me</p>")
            });   

            $(".test").click(function(){
                alert();
            });
        });

    </script>
</head>
<body>
    <h2></h2>
    <button>generate new element</button>
</body>
</html>

Я пытался создать новый тег с именем класса test в <h2>, нажав кнопку. Я также определил событие click, связанное с test. Но событие не работает.

Может ли кто-нибудь помочь?

  • 1
    jsfiddle.net/yz2yn ?
  • 0
    попробуйте использовать <input id = "button" type = "button" value = "генерировать новый элемент">. Он регистрирует новый идентификатор в DOM, к которому jQuery может получить доступ, а <button> - нет.
Показать ещё 3 комментария
Теги:
events

20 ответов

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

Связывание click(), которое вы используете, называется "прямой" привязкой, которая привязывает обработчик только к уже существующим элементам. Он не будет привязан к элементам, созданным в будущем. Для этого вам нужно будет создать "делегированное" привязку с помощью on().

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

Источник

Здесь вы ищете:

var counter = 0;

$("button").click(function() {
    $("h2").append("<p class='test'>click me " + (++counter) + "</p>")
});

// With on():

$("h2").on("click", "p.test", function(){
    alert($(this).text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<h2></h2>
<button>generate new element</button>

Вышеупомянутое работает для тех, кто использует jQuery версии 1.7+. Если вы используете более старую версию, см. Предыдущий ответ ниже.


Предыдущий ответ:

Попробуйте использовать live():

$("button").click(function(){
    $("h2").html("<p class='test'>click me</p>")
});   


$(".test").live('click', function(){
    alert('you clicked me!');
});

Работал для меня. Пробовал его с помощью jsFiddle.

Или есть новый способ общения с delegate():

$("h2").delegate("p", "click", function(){
    alert('you clicked me again!');
});

Обновленный jsFiddle.

  • 9
    Начиная с jQuery 1.7, метод .live() устарел. Используйте .on() чтобы присоединить обработчики событий.
  • 50
    Это должен быть $(document).on('click', '.test', function() { или привязанный к другому родителю, чтобы быть равным .live Only, говоря, потому что он возник в недавнем вопросе
Показать ещё 14 комментариев
170

Используйте метод .on() с делегированными событиями

$('#staticParent').on('click', '.dynamicElement', function() {
    // Do something on an existent or future .dynamicElement
});

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

P.S: Не используйте .live()! Из jQuery 1.7+ метод .live() устарел.

  • 47
    Это сработало для меня. Забавно, что ни один из ответов выше не указывает на тот факт, что необходимо использовать нединамический родительский селектор. Неудивительно, что «.on» раньше не работал для меня.
  • 4
    Этот также работал для меня, где те, что выше не сделали. Спасибо!
Показать ещё 10 комментариев
52

Причина:

Click() - прикрепляет обработчик событий только в том случае, если элемент уже существует в html-коде.

Он не будет рассматривать новый элемент, который создается динамически (элемент Future) после загрузки страницы.

Динамические элементы создаются с помощью javascript или jquery (не в html).

Таким образом, событие click не срабатывает.

Решение:

Чтобы преодолеть это, мы должны использовать функцию on().

функции delegate(), live() и on() имеют преимущества перед элементами DOM.

on может запускать как существующие элементы, так и будущие элементы.

on может рассматривать элементы, которые присутствуют на всей странице.

Функции делегата(), live() устарели (не используйте их).

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

Удалите код из $(document).ready:

$(".test").click(function(){

  alert();

});

Изменить на:

$(document).on('click','.test',function(){

  alert('Clicked');

});
  • 2
    Отличный ответ для ситуации, когда родитель не существует и тоже создается динамически.
  • 0
    Спасибо, это работа ..
Показать ещё 5 комментариев
11

Измените

 $(".test").click(function(){

To

 $(".test").live('click', function(){

LIVE DEMO

jQuery .live()

11

Для этого вам нужно использовать . live:

$(".test").live("click", function(){
   alert();
});

или если вы используете jquery 1.7+, используйте .:

$(".test").on("click", "p", function(){
   alert();
});
  • 0
    Прочитайте DOCS о делегированных событиях, пожалуйста. Где делегированы элементы вашего мероприятия? Другой пример, который вы показали (используя .on ()), не является точным способом замены .live() в любом случае.
8

Попробуйте .live() или .delegate()

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

http://api.jquery.com/delegate/

Ваш .test элемент был добавлен после метода .click(), поэтому у него не было привязанного к нему события. Live и Delegate придают этому событию триггер родительским элементам, которые проверяют своих детей, поэтому все, что добавлено впоследствии, все еще работает. Я думаю, что Live проверит весь документ, а делегат может быть передан элементу, поэтому делегирование будет более эффективным.

Дополнительная информация:

http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/

  • 0
    .live() jQuery 1.71, .live() устарела, а delegate() заменен методом .on ()
7

Добавить эту функцию в файл js.  Он будет работать в каждом браузере

$(function() {
    $(document).on("click", '#mydiv', function() {
        alert("You have just clicked on ");
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='mydiv'>Div</div>
5

Лучший способ применить событие к динамически сгенерированному контенту с помощью делегирования.

$(document).on("eventname","selector",function(){
    // code goes here
});

поэтому ваш код будет таким же, как сейчас.

$(document).on("click",".test",function(){
    // code goes here
});
5

Я нашел два решения в документации jQuery:

Сначала: используйте делегат на теле или документе

Например:

 $("body").delegate('.test', 'click', function(){
 ...
  alert('test');
 });

Почему?

Ответ.. Прикрепите обработчик к одному или нескольким событиям для всех элементов, которые соответствуют селектору, сейчас или в будущем, на основе определенного набора корневых элементов. ссылка: http://api.jquery.com/delegate/

Второе: поместите свою функцию в "$ (document)", используя "on" и присоедините ее к элементу, который вы хотите вызвать. Первым параметром является "обработчик событий", второй: элемент и третий: функция. Например:

 $( document ).on( 'click', '.test', function () {
 ...
  alert('test');
 });

Почему?

Ответ: Обработчики событий привязаны только к выбранным в данный момент элементам; они должны существовать на странице в момент, когда ваш код выполняет вызов .on(). Чтобы убедиться, что элементы присутствуют и могут быть выбраны, выполните привязку событий внутри обработчика документа для элементов, которые находятся в разметке HTML на странице. Если на страницу вводится новый HTML-код, выберите элементы и присоедините обработчики событий после того, как новый HTML будет помещен на страницу. Или используйте делегированные события для присоединения обработчика событий, как описано далее... ссылка: https://api.jquery.com/on/

4

Проблема заключается в том, что вы пытаетесь связать класс "test" с событием, прежде чем что-либо с классом "test" в DOM. Хотя может показаться, что все это динамично, на самом деле происходит то, что JQuery делает проход через DOM и прокручивает событие click при запуске функции ready(), что происходит до того, как вы создали "Click Me", в событии кнопки.

Добавив событие "test" Click к обработчику кликов "button", он подключится к нему после того, как правильный элемент существует в DOM.

<script type="text/javascript">
    $(document).ready(function(){                          
        $("button").click(function(){                                  
            $("h2").html("<p class='test'>click me</p>")                          
            $(".test").click(function(){                          
                alert()                          
            });       
        });                                     
    });
</script>

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

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

3

Также вы можете использовать onclick="do_something(this)" внутри элемента

3

Я не мог заставить жить или делегировать работу над div в лайтбокс (tinybox).

Я использовал setTimeout успешно, следующим простым способом:

$('#displayContact').click(function() {
    TINY.box.show({html:'<form><textarea id="contactText"></textarea><div id="contactSubmit">Submit</div></form>', close:true});
    setTimeout(setContactClick, 1000);
})

function setContactClick() {
    $('#contactSubmit').click(function() {
        alert($('#contactText').val());
    })
}
3

Альтернативной и более сжатой альтернативой (IMHO) является использование сырой функции javascript, которая реагирует на событие on click, а затем передает целевой элемент обратно в jQuery, если хотите. Преимущество этого подхода заключается в том, что вы можете динамически добавлять свой элемент в любом месте, а обработчик кликов будет "работать", и вам не нужно заниматься делегированием элемента управления родительским элементам и т.д.

Шаг 1: Обновите динамический html, чтобы запустить событие onclick. Не забудьте передать объект "событие" в качестве аргумента


    $("button").click(function() {
        $("h2").html("<p class='test' onclick='test(event)'> click me </p>")
    });

Шаг 2: Создайте тестовую функцию для ответа на событие click


    function test(e){
        alert();
    });

Дополнительно Шаг 3: Учитывая, что вы используете jQuery, я предполагаю, что будет полезно вернуть ссылку на кнопку источника

<Предварительно >   функциональный тест (e) {       предупреждение();       // Получить ссылку на кнопку       // Объяснение этой строки доступно здесь      var target = (e.target)? e.target: e.srcElement;       // Передаем ссылку на кнопку jQuery для создания jQuery magic       var $btn = $(target);   });
3
$(.surrounding_div_class).on( 'click', '.test', function () {
alert( 'WORKS!' );
});

Будет работать только в том случае, если DIV с классом .surrounding_div_class является непосредственным родителем объекта .test

Если в div будет другой объект, который будет заполнен, он не будет работать.

3

JQuery .on работает нормально, но у меня были некоторые проблемы с рендерингом, реализующим некоторые из вышеперечисленных решений. Моя проблема с использованием .on заключается в том, что каким-то образом она отображала события иначе, чем метод .hover.

Просто fyi для всех, у кого также может быть проблема. Я решил свою проблему, перерегистрировав событие наведения для динамически добавленного элемента:

перерегистрируйте событие зависания, потому что наведение не работает для динамически созданных элементов. поэтому каждый раз, когда я создаю новый/динамический элемент, я снова добавляю код наведения. отлично работает

$('#someID div:last').hover(
    function() {
       //...
    },
    function() {
       //...
    }
);
  • 1
    hover - это оболочка для mouseenter и mouseleave ( api.jquery.com/mouseenter ), а они, в свою очередь, являются оболочками для .on('mouseenter', handler) . Так что это использует .on внизу! Так что я не понимаю, как это сильно .on на использование .on . Похоже, что вы упустили что-то еще здесь.
3

.live отлично работает.

Это для динамически добавленных элементов на сцену.

$('#selectAllAssetTypes').live('click', function(event){
                    alert("BUTTON CLICKED");
                    $('.assetTypeCheckBox').attr('checked', true);
                });

Cheers, Анкит.

  • 3
    По состоянию на Jquery 1.7 в прямом эфире устарела .on. Это было даже удалено с Jquery 1.9. api.jquery.com/live
2

Если у вас есть динамически добавленная ссылка на какой-либо контейнер или тело:

var newLink= $("<a></a>", {
        "id": "approve-ctrl",
        "href": "#approve",
        "class": "status-ctrl",
        "data-attributes": "DATA"
    }).html("Its ok").appendTo(document.body);

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

newLink.get(0).addEventListener("click", doActionFunction);

Независимо от того, сколько раз вы добавляете этот экземпляр новой ссылки, вы можете использовать его так, как если бы вы использовали функцию jquery click.

function doActionFunction(e) {
    e.preventDefault();
    e.stopPropagation();

    alert($(this).html());
}

Итак, вы получите сообщение с сообщением

Его ok

Он имеет лучшую производительность, чем другие альтернативы.

Дополнительно. Вы можете получить лучшую производительность, избегая jquery и используя простой javascript. Если вы используете IE до версии 8, вы должны использовать этот polyfill для использования метода addEventListener

if (typeof Element.prototype.addEventListener === 'undefined') {
    Element.prototype.addEventListener = function (e, callback) {
      e = 'on' + e;
      return this.attachEvent(e, callback);
    };
  }
2

Вы можете добавить на клик динамически создаваемые элементы. Пример ниже. Использование команды "Когда", чтобы убедиться в ее выполнении. В моем примере я захватываю div с расширением класса, добавляя "щелчок, чтобы увидеть больше", а затем используя этот интервал, чтобы скрыть/показать оригинальный div.

$.when($(".expand").before("<span class='clickActivate'>Click to see more</span>")).then(function(){
    $(".clickActivate").click(function(){
        $(this).next().toggle();
    })
});
2

Я работаю с таблицами, динамически добавляя им новые элементы, а при использовании on() единственный способ сделать это работает для меня - использовать нединамический родитель, как:

<table id="myTable">
    <tr>
        <td></td> // Dynamically created
        <td></td> // Dynamically created
        <td></td> // Dynamically created
    </tr>
</table>

<input id="myButton" type="button" value="Push me!">

<script>
    $('#myButton').click(function() {
        $('#myTable tr').append('<td></td>');
    });

    $('#myTable').on('click', 'td', function() {
        // Your amazing code here!
    });
</script>

Это действительно полезно, потому что для удаления событий, связанных с on(), вы можете использовать off(), а для использования событий один раз вы можете использовать one().

0

Используйте 'on', поскольку щелчок получает привязку к уже присутствующим элементам.

Например,

$('test').on('click',function(){
    alert('Test');
})

Это поможет.

Ещё вопросы

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