jQuery упрощает обработку событий в JavaScript. Однако чем больше определяемых вами обработчиков событий, тем больше памяти вы используете, что может привести к снижению производительности и замедлению пользовательского интерфейса. В этой статье рассматривается, как делегирование событий может помочь предотвратить это, и как вы можете применить делегирование событий с помощью jQuery.
Делегирование событий — это метод обработки событий, при котором вместо того, чтобы прикреплять обработчики событий непосредственно к каждому элементу, для которого вы хотите прослушивать события, вы присоединяете отдельный обработчик событий к родительскому элементу этих элементов, чтобы прослушивать события, происходящие в его дочерних элементах. При обработке события вы проверяете, какой элемент вызвал событие, и отвечаете соответствующим образом. Делегирование событий зависит от всплытия событий в DOM. Это процесс, при котором событие, инициируемое в дочернем элементе, распространяется по дереву DOM до его родительского элемента, родительского элемента его родителя и т. Д. До тех пор, пока не будет достигнут document
. Пузырьки также могут быть остановлены программистом с помощью event.stopPropagation()
. Обратите внимание, что не все события DOM распространяются — фокус, размытие, загрузка и выгрузка не происходят.
Делегирование событий использует меньше памяти, поскольку вы заменяете несколько обработчиков событий одним обработчиком событий. Например, если вы прикрепите обработчики событий к каждой ссылке в списке из десяти ссылок, у вас будет десять обработчиков событий, занимающих место в памяти. Если вместо этого вы используете делегирование событий и обрабатываете события в родительском элементе <ul>
, вы создаете только один обработчик событий и используете меньше памяти, чем вы бы прикрепили к каждой ссылке отдельно. Помимо снижения потребления памяти делегирование событий также имеет следующие преимущества.
- Нет необходимости вручную управлять событиями, когда элементы добавляются или удаляются из DOM. Если бы мы использовали традиционную обработку событий, нам пришлось бы присоединять обработчики событий к элементам, добавленным в DOM, и удалять обработчики событий из элементов, удаленных из DOM.
- Меньше кода для управления благодаря меньшему количеству функций обработки событий. Это может оставить нас с более простым кодом, без какой-либо дублированной логики обработки событий, что может помочь сделать наш JavaScript красивым и сухим .
Пример делегирования события в jQuery
Предположим, вы разрабатываете одностраничное приложение, которое продает фотографии котят. Когда страница загружается, отображаются первые 20 котят. Когда пользователь прокручивает страницу вниз, загружается больше котят. Наш HTML показан ниже.
<section id="cats"> <ul> <li> <img src="http://placekitten.com/200/200" alt=""/> <a href="/moreinfo">More info</a> <button>Add to cart</button> </li> ... </ul> </section>
При традиционной обработке событий нам нужно подключить обработчики событий к:
- Отображать увеличенное изображение, когда пользователь нажимает на миниатюру.
- Отображение дополнительной информации, когда пользователь нажимает на ссылку «Подробнее».
- Добавьте изображение в корзину, когда пользователь нажмет «Добавить в корзину».
- Присоедините эти три события к новым элементам DOM, которые добавляются по мере прокрутки пользователем страницы вниз.
Этот код будет похож на следующий пример. Обратите внимание, что это стандартный код, предназначенный для демонстрации того, как присоединение обработчиков событий к отдельным элементам отличается от использования делегирования событий, поэтому реализация для loadImage()
, moreInfo()
, addToCart()
и loadNewKittens()
.
$(document).ready(function() { var cats = $('#cats'); cats.find('img') .on('click', function() { loadImage(); }) cats.find('a') .on('click', function(event) { event.preventDefault(); moreInfo(); }); cats.find('button') .on('click', function() { addToCart(); }); $(window).scroll(function() { var fragment = loadNewKittens(); // attach event handlers for new DOM elements fragment.find('img') .on('click', function() { loadImage(); }); fragment.find('a') .on('click', function(event) { event.preventDefault(); moreInfo(); }); fragment.find('button') .on('click', function() { addToCart(); }); fragment.appendTo('#cats ul'); }); });
Это довольно много кода. Теперь давайте посмотрим, как выглядит наш код, если вместо этого мы используем делегирование событий:
$(document).ready(function() { $('#cats') .on('click', 'img, a, button', function(event) { event.preventDefault(); var target = event.target; switch(target.tagName.toLowerCase()) { case 'img': loadImage(); break; case 'a': moreInfo(); break; case 'button': addToCart(); break; default: // do nothing } }); $(window).scroll(function() { var fragment = loadNewKittens(); fragment.appendTo('#cats ul'); }); });
Ключ является необязательным вторым аргументом для on()
. Передавая здесь селектор, on()
знает, что он имеет дело с делегированным обработчиком событий, а не с напрямую связанным обработчиком событий.
Наш код обработки событий теперь намного проще. Получив event.target
и включив его tagName
, мы можем сказать, какой элемент tagName
событие и может ответить соответствующим образом. Кроме того, нам больше не нужно прикреплять обработчики событий для элементов, загруженных в $(window).scroll
, поскольку события, $(window).scroll
этими новыми элементами, делегируются родительскому элементу.
Потенциальная «ошибка», которую нужно знать при использовании делегирования событий, заключается в том, что любые обработчики событий, связанные с дочерними элементами, обрабатываются до того, как сработает обработчик удаленных событий. Следовательно, дочерний обработчик события может вызвать event.stopPropagation()
или return false
, что предотвратит event.stopPropagation()
события в делегированный обработчик события и оставит вас в голове, почему ваше событие не делегируется. ,
Вывод
В этой статье мы рассмотрели делегирование событий. Мы увидели, как это может помочь повысить производительность вашего сайта за счет уменьшения нагрузки, связанной с обработкой событий. Мы также видели, как реализовать делегирование событий в jQuery с помощью функции on()
.