Делегирование событий в JS

Делегирование событий в JS

От автора: основной алгоритм работы при использовании библиотеки jQuery заключается в отборе элементов в коллекцию и совершении каких либо действий при наступлении того или иного события для выбранной коллекции. Все это легко сделать с элементами, которые были на странице изначально, т.е. находятся в исходном коде. Однако нередко на страницу динамически добавляются новые элементы. И вот здесь есть некоторые нюансы при отслеживании событий для вновь добавленных элементов. В этом уроке мы рассмотрим эти нюансы и познакомимся с таким понятием, как делегирование событий.

автор

Автор: Андрей Кудлай

Зовут меня Андрей Кудлай. Родом я из Украины, живу в Днепропетровске. Веб-программированию учился сам. Неплохо знаю HTML, CSS, PHP, JavaScript.

скачать исходникискачать урок

Итак, для нашего примера добавим на страницу таблицу и кнопку:

<button id="add">Добавить строку</button>

<table class="zebra">
	<thead>
		<tr>
			<th>#</th>
			<th>Наименование</th>
			<th>Цена</th>
			<th>Об услуге</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td>1</td>
			<td>Замена аккумулятора в iPad 2</td>
			<td>1171 грн.</td>
			<td><a href="#">Подробнее</a></td>
		</tr>
		<tr>
			<td>2</td>
			<td>Замена Виброзвонка в iPhone 5</td>
			<td>1171 грн.</td>
			<td><a href="#">Подробнее</a></td>
		</tr>
	</tbody>	
</table>

Добавим немного стилей:

.zebra{
	width: 100%;
}
.zebra th{
	background: #555;
	color: #fff;
}
.zebra input{
	width: 100%;
}
.zebra th:first-child,
.zebra td:first-child{
	width: 100px;
	text-align: center;
}
.zebra th,
.zebra td{
	border-bottom: 1px solid #ccc;
	/*border: 1px solid #ccc;*/
	padding: 5px;
	vertical-align: middle;
	padding: 14px 0;
}
.zebra tr{
	transition: all .5s;
}
tr:hover,
.stroke{
	background: #cfcfcf;
}
table{
	border-collapse: collapse;
}

Теперь подключим библиотеку jQuery версии 1.8.3 (далее вы поймете, почему нужна версия не выше данной):

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>

Итак, по задумке при клике по любой строке таблицы для этой строки должна фиксироваться подсветка, т.е. строка должна оставаться выделенной. Для этого в стилях предусмотрен класс stroke. При повторном клике этот класс должен удаляться и подсветка со строки убирается. Все просто.

<script>
	$(function(){
		$(".zebra tr").click(function(){
			$(this).toggleClass("stroke");
		});
	});
</script>

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

<script>
	$(function(){
		var html = '<tr><td>XX</td><td>Новая строка</td><td>ХХХХ грн.</td><td><a href="#">Подробнее</a></td></tr>';
		$(".zebra tr").click(function(){
			$(this).toggleClass("stroke");
		});

		$("#add").click(function(){
			$(".zebra tbody").append(html);
		});
	});
</script>

Если попробуем добавить несколько строк, то увидим, что ни для одной новой строки класс не устанавливается. Для уже имеющихся строк все работает, как и прежде. Как же быть? Здесь нам нужно обратиться, к т.н. делегированной обработке событий, т.е. делегировать событие клика для добавляемых строк. Подробнее о делегировании событий можно прочесть в этой статье.

До версии 1.9 (именно поэтому мы подключили библиотеку 1.8.3) для этой цели мы можем использовать метод live(), т.н. умный обработчик событий. Использование этого метода довольно просто. Давайте немного перепишем код:

<script>
	$(function(){
		var html = '<tr><td>XX</td><td>Новая строка</td><td>ХХХХ грн.</td><td><a href="#">Подробнее</a></td></tr>';
		$(".zebra tr").live("click", function(){
			$(this).toggleClass("stroke");
		});

		$("#add").click(function(){
			$(".zebra tbody").append(html);
		});
	});
</script>

Вот теперь все работает, как нам и нужно. Класс меняется теперь и для добавленных строк. Однако здесь есть ложка дегтя. Дело в том, что метод live() с версии 1.9 был удален. Таким образом, если вам нужно использовать библиотеку jQuery версии 1.9 или выше, то текущий код работать не будет. Вместо метода live() теперь для делегирования событий можно использовать метод on(). Этот метод чуть сложнее в использовании и понимании (недаром метод live() назван умной обработкой событий), но стоит разобраться в его использовании, и вы поймете, что на самом деле ничего сложного нет.

Итак, перепишем код с учетом использования метода on():

<script>
	$(function(){
		var html = '<tr><td>XX</td><td>Новая строка</td><td>ХХХХ грн.</td><td><a href="#">Подробнее</a></td></tr>';
	
		$(".zebra").on("click", "tr", function(){
			$(this).toggleClass("stroke");
		});

		$("#add").click(function(){
			$(".zebra tbody").append(html);
		});
	});
</script>

Как видим, здесь в коллекцию мы отбираем не строки, а всю таблицу целиком. А вот в методе on() использован вторым параметром указатель на те элементы, для которых событие (указано первым параметром) делегируется. Т.е. получается, что мы должны взять некий внешний контейнер (таблица) и делегировать событие для составных элементов (строки). Вот, собственно, и все, ничего сложного нет.

На этом текущий урок завершен. Удачи и до новых встреч!

JavaScript&jQuery с нуля до профи

Пройдите пошаговый видеокурс по JavaScript&jQuery

Научиться

Метки: ,

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (6)

  1. Максим

    Андрей а как работать с событием hover через метод on?

    Там же получается две функции — при наведени мыши и при уведении..

    • Богдан

      Функция hover — это короткая запись такого:
      $( selector ).mouseenter( handlerIn ).mouseleave( handlerOut );

  2. Iryna

    Андрей, вот люблю я Ваши уроки)
    Всё разложено по полочкам, было много вопросов – не осталось ни одного.
    И как я раньше не видела этот урок? Уже чуть было на форум не побежала со своими вопросами…
    Спасибо Вам большое-пребольшое!!!

  3. Андрей

    А с более поздними версиями JQuery, нет вариантов работы, с динамически добавляемыми объектами?

    • Богдан

      Так делегирование для того и существует. Мы детектим всплытие на корневом элементе, будь это document или какой-то конкретный. И уточняем, какой именно элемент вызвал это всплытие. То есть мы делегируем событие на корневой элемент.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree