Уроки JavaScript – не работают события jQuery после AJAX загрузки
Если вы используете AJAX на своем сайте, имейте в виду, что такие события, как клик (click), отправка (submit), наведение (hover), могут не работать, если вы не прикрепите их правильно. В сегодняшней статье мы рассмотрим практическое решение проблемы, когда не срабатывают события в jQuery после динамического изменения страницы (или AJAX).
Описание задачи
Допустим, у нас есть блоки с заголовком и скрытым контентом в теге <p>
. По клику на заголовке, скрытый контент показывается/прячется с помощью функции toggle()
:
$('a.zagolovok').click(function(e){ e.preventDefault(); $(this).next('p').toggle(); });
Потом мы загружаем новые элементы (блоки) без перезагрузки страницы с помощью AJAX. Когда мы перезагружаем страницу – все работает нормально, но если новые элементы подгружаются AJAX’ом, — не работает функция toggle()
.
Вариант решения №1
Событие click
прикрепляется к существующим элементам после полной загрузки страницы. Ключевое слово здесь – существующим. Когда мы загружаем что-то с помощью AJAX, мы манипулируем DOM. Мы размещаем абсолютно новый элемент, который не существовал при загрузке страницы. Поэтому нам нужно прикрепить это событие после подгрузки нового контента. Если вы используете функцию .load()
(которая загружает данные с сервера и помещает возвращенный HTML в соответствующие элементы), вам просто нужно поместить функцию click()
в функцию обратного вызова:
$('.blocks-wrapper').load(link.attr('href'), function(responseText, textStatus, XMLHttpRequest){ $('a.zagolovok').click(function(e){ e.preventDefault(); $(this).next('p').toggle(); }); });
Так мы прикрепляем событие click
и к новым добавленным элементам.
Если вы используете функцию .ajax()
вместо .load()
, просто присоедините событие к функции .done()
(которая добавляет обработчик, что будет вызываться при обработке отложенного объекта) AJAX вызова.
Вариант решения №2
Что делать, если мы не хотим прикреплять событие каждый раз, когда вызывается AJAX? Для этого есть другое, более «глобальное» решение. Мы можем использовать функцию .on()
.
Функция .click()
похожа с .on('click')
, но здесь есть одна важная часть – при второй функции мы можем делегировать событие. Преимущество делегированных событий заключается в том, что они могут обрабатывать события для элементов-потомков, которые добавляются в документ позднее (например, при AJAX).
Поэтому вместо того, чтобы прикреплять событие click
к завершенному AJAX, мы просто добавляем его более «глобально»:
$('.blocks-wrapper').on('click', 'a.zagolovok', function(e){ e.preventDefault(); $(this).next('p').toggle(); });
Мы могли бы присоединить обработчик и к тегу <body>
, но лучше прикреплять делегированные события как можно ближе к целевым элементам в документе. Нужно избегать чрезмерного использования document
или document.body
для делегированных событий на больших страницах с большим DOM.
Делегированное событие должно быть присоединено к элементу, который существует на странице в то время, когда ваш код выполняет вызов, и не изменяется во время AJAX вызовов.
В более ранних версиях jQuery вместо .on()
использовались функции .live()
(устарела с версии jQuery 1.9) или .delegate()
(устарела с версии jQuery 3.0).