Описание тега event-delegation
Вы можете использовать этот тег, если ваш вопрос звучит примерно так:
- Я динамически вставлял / изменял узлы в свой документ, и теперь они не обрабатывают события.
- Как привязать обработчики событий к еще не существующим узлам?
- Я привязываю к своему документу тысячи обработчиков событий, и теперь он работает очень медленно.
- Мне нужно привязать один и тот же обработчик событий к множеству разных элементов. Нет более легкого пути?
Если да, то вы можете использовать делегирование событий. Преимущества делегирования:
- Используйте один обработчик для захвата множества событий на разных узлах.
- Поддержка динамических изменений страниц без необходимости постоянно повторно связывать обработчики событий.
Чтобы понять делегирование, вы сначала должны быть знакомы с всплыванием событий.
Пузыри
Многие из наиболее распространенных событий в JavaScript "всплывают" вверх по дереву DOM. Например, рассмотрим следующий HTML:
<div id="imageDiv">
<img src="/abc.png" class="clickable"/>
<img src="/def.png" class="clickable"/>
<img src="/ghi.png" class="clickable"/>
<p>
<img src="/jkl.png" class="clickable"/>
</p>
</div>
Если пользователь нажимает на jkl.png
image событие щелчка будет запущено сначала на самом изображении, затем на содержащем его абзаце, а затем на div
элемент и т. д. вплоть до объекта документа.
Узнать больше о Event Bubbling
Отличная статья о Bubbling vs Catching
Делегация
Вы можете воспользоваться восходящей цепью событий, чтобы реализовать единый обработчик для большого количества узлов.
Вместо привязки четырех обработчиков событий щелчка (по одному для каждого изображения) вам нужен только один обработчик, прикрепленный к div
элемент. Объект события содержит информацию о том, какой элемент изначально получил событие (цель). Вы можете протестировать цель, чтобы узнать, следует ли обрабатывать событие или нет.
Здесь мы привязываем обработчик кликов к div#imageDiv
и использовать его для обработки событий щелчка на изображениях-потомках:
document.getElementById('imageDiv').onclick = function(evt) {
if (evt.target.className == 'clickable') {
// ... do something here ...
}
};
Теперь ваш единственный обработчик будет улавливать все события щелчка для всех изображений внутри div#imageDiv
. Также вы можете добавлять изображения вdiv#imageDiv
динамически и не нужно беспокоиться о привязке к ним новых обработчиков кликов.
Конечно, есть проблемы совместимости браузера с тем, как всплывают некоторые события, и с поиском исходной цели события. Вот почему хорошая библиотека JavaScript предоставит вам удобную команду для делегирования. jQuery предоставляет метод on():
$('#imageDiv').on('click', 'img.clickable', function(evt) {
// ... "this" is the image that was clicked ...
});