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

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

Всплытие и перехват событий позволяет реализовать один из самых важных приёмов разработки – делегирование.

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

Рассмотрим пример – диаграмму Ба-Гуа. Это таблица, отражающая древнюю китайскую философию.

Её HTML (схематично):

В этой таблице всего 9 ячеек, но могло бы быть и 99, и даже 9999, не важно.

Наша задача – реализовать подсветку ячейки

при клике.

Вместо того, чтобы назначать обработчик onclick для каждой ячейки

(их может быть очень много) – мы повесим «единый» обработчик на элемент

.

Такому коду нет разницы, сколько ячеек в таблице. Мы можем добавлять, удалять

из таблицы динамически в любое время, и подсветка будет стабильно работать.

Однако, у текущей версии кода есть недостаток.

Клик может быть не на теге

, а внутри него.

В нашем случае, если взглянуть на HTML-код таблицы внимательно, видно, что ячейка

содержит вложенные теги, например :

Внутри обработчика table.onclick мы должны по event.target разобраться, был клик внутри

или нет.

Вот улучшенный код:

В итоге мы получили короткий код подсветки, быстрый и эффективный, которому совершенно не важно, сколько всего в таблице

.

Применение делегирования: действия в разметке

Есть и другие применения делегирования.

Первое, что может прийти в голову – это найти каждую кнопку и назначить ей свой обработчик среди методов объекта. Но существует более элегантное решение. Мы можем добавить один обработчик для всего меню и атрибуты data-action для каждой кнопки в соответствии с методами, которые они вызывают:

Обработчик считывает содержимое атрибута и выполняет метод. Взгляните на рабочий пример:

Так что же даёт нам здесь делегирование?

Приём проектирования «поведение»

Делегирование событий можно использовать для добавления элементам «поведения» (behavior), декларативно задавая хитрые обработчики установкой специальных HTML-атрибутов и классов.

Приём проектирования «поведение» состоит из двух частей:

Поведение: «Счётчик»

Например, здесь HTML-атрибут data-counter добавляет кнопкам поведение: «увеличить значение при клике»:

Если нажать на кнопку – значение увеличится. Конечно, нам важны не счётчики, а общий подход, который здесь продемонстрирован.

Элементов с атрибутом data-counter может быть сколько угодно. Новые могут добавляться в HTML-код в любой момент. При помощи делегирования мы фактически добавили новый «псевдостандартный» атрибут в HTML, который добавляет элементу новую возможность («поведение»).

Поведение: «Переключатель» (Toggler)

Ещё один пример поведения. Сделаем так, что при клике на элемент с атрибутом data-toggle-id будет скрываться/показываться элемент с заданным id :

Это бывает очень удобно – не нужно писать JavaScript-код для каждого элемента, который должен так себя вести. Просто используем поведение. Обработчики на уровне документа сделают это возможным для элемента в любом месте страницы.

Мы можем комбинировать несколько вариантов поведения на одном элементе.

Шаблон «поведение» может служить альтернативой для фрагментов JS-кода в вёрстке.

Итого

Делегирование событий – это здорово! Пожалуй, это один из самых полезных приёмов для работы с DOM.

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

Конечно, у делегирования событий есть свои ограничения:

Задачи

Спрячьте сообщения с помощью делегирования

В результате должно работать вот так:

P.S. Используйте делегирование событий. Должен быть лишь один обработчик на элементе-контейнере для всего.

Раскрывающееся дерево

Создайте дерево, которое по клику на заголовок скрывает-показывает потомков:

Решение состоит из двух шагов:

Сортируемая таблица

Сделать таблицу сортируемой: при клике на элемент

строки таблицы должны сортироваться по соответствующему столбцу.

Каждый элемент

имеет атрибут data-type:

В примере выше первый столбец содержит числа, а второй – строки. Функция сортировки должна это учитывать, ведь числа сортируются иначе, чем строки.

P.S. Таблица может быть большой, с любым числом строк и столбцов.

Поведение «подсказка»

Напишите JS-код, реализующий поведение «подсказка».

Пример HTML с подсказками:

Результат в ифрейме с документом:

В этой задаче мы полагаем, что во всех элементах с атрибутом data-tooltip – только текст. То есть, в них нет вложенных тегов (пока).

Для решения вам понадобятся два события:

После реализации поведения – люди, даже не знакомые с JavaScript смогут добавлять подсказки к элементам.

Источник

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

что такое делегирование событий. Смотреть фото что такое делегирование событий. Смотреть картинку что такое делегирование событий. Картинка про что такое делегирование событий. Фото что такое делегирование событий

На прошлом уроке мы научились вешать обработчик события на одну кнопку в JS. Однако методы, хорошо работающие с единичными объектами, совершенно не эффективны для массовых манипуляций. Пример из реальной жизни: Директор школы не подходит к каждому новому ученику, чтобы сообщить ему о школьных правилах. Эту почетную миссию он делегирует классному руководителю, чтобы каждый новый ученик знал общие правила.

На странице имеется какое-то количество навигационных ссылок, на которых при клике будут срабатывать одинаковые события. Навесить на каждую кнопку по событию не так и сложно. Но есть одна проблема. А что если пользователь сайта (заказчик) добавит через админку новую ссылку. У добавленной ссылки уже не будет события. Делегирование событий обезопасит вас от подобных косяков. Правильно будет работать сразу с родительским элементом, а не с каждым дочерним по отдельности. Тогда каждый новый добавленный элемент в родительский блок, автоматически унаследует и его событие.

Пример с делегированием в JS

Перед нами обычный список, где теги li являются дочерними для тега ul. Мы будем работать с родителем всех li.

let ul = document.querySelector(‘ul’);
li = document.querySelectorAll(‘li’);

Навешиваем обработчик события addEventListener на родителя и первым параметром передаем событие клик (можно любое событие). Вторым параметром передаем callback функцию с передаваемым объектом события (event), чтобы свойства объекта могли вызываться внутри, функции и выведем их в консоль. Нас интересует, как в DOM прописано значение у свойства tagName.

ul.addEventListener(‘click’, function(event) <
console.log(event);
>);

Свойства выведутся в консоль при клике по списку. Раскрываем всю эту цепочку MouseEvent → target → tagName. Дословный перевод: событие мыши → цель → имя тега. Начинающие разработчики часто заглядывают в консоль, поскольку визуализируя процесс, проще понять смысл происходящего и увидеть ошибки.

что такое делегирование событий. Смотреть фото что такое делегирование событий. Смотреть картинку что такое делегирование событий. Картинка про что такое делегирование событий. Фото что такое делегирование событий

Суть делегирования событий

Нам нужно проверить, куда кликнул пользователь, если он кликнул по списку, то выполнится какое-то действие.

if(event.target && event.target.tagName == ‘LI’) <
console.log(‘Привет!’)
>

Нас не интересуют только клики по пунктам списка. Если целью события клика event, оказался тег LI, то в консоль выведется слово Привет!

В первой части условия event.target мы проверяем, есть ли у объекта события свойство target. Во второй части условия, после оператора AND, мы проверяем, а действительно ли кликнули по тегу li.

что такое делегирование событий. Смотреть фото что такое делегирование событий. Смотреть картинку что такое делегирование событий. Картинка про что такое делегирование событий. Фото что такое делегирование событий

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

Пример кода целиком.

let ul = document.querySelector(‘ul’);
li = document.querySelectorAll(‘li’);

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

Всплытие событий в JS

что такое делегирование событий. Смотреть фото что такое делегирование событий. Смотреть картинку что такое делегирование событий. Картинка про что такое делегирование событий. Фото что такое делегирование событий

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

Комментарии ( 0 ):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.

Источник

События и делегирование событий

Родное имя событияСокращённый метод
click.click()
keydown.keydown()
keypress.keypress()
keyup.keyup()
mouseover.mouseover()
mouseout.mouseout()
mouseenter.mouseenter()
mouseleave.mouseleave()
scroll.scroll()
focus.focus()
blur.blur()
resize.resize()

После того как к элементу «привязали» обработчик событий, вы можете инициировать его через jQuery.

Если у события, которое вы хотите инициировать, есть сокращённый метод (см. таблицу выше), вы также можете инициировать это событие, просто вызывая сокращённый метод:

Пространство имён событий

Внимание! Неудачное решение

Однако это отвяжет все обработчики click для всех элементов, чего нам не хочется. Если вы привяжете обработчик событий с помощью пространства имён событий, то можно задать конкретные обработчики событий:

Мы также можем использовать пространства имен, чтобы инициировать только определённые события:

Привязка нескольких событий за раз

Именованная функция как обработчик событий

До сих пор во всех наших примерах в качестве обработчика событий мы передавали анонимную функцию. Тем не менее, вы можете создать функцию заранее и хранить её в переменной, а затем передать эту переменную в качестве обработчика событий. Это полезно, если вы хотите использовать один и тот же обработчик для разных событий или одно событие для различных элементов.

Объект события

Всякий раз, когда происходит событие, функция обработчика событий получает один аргумент — объект события, стандартный во всех браузерах. Этот объект имеет много полезных свойств, в том числе следующие:

Внутри обработчика событий

Отмена действия по умолчанию

Это позволяет нам использовать «всплывающие» события, которые мы исследуем ниже.

Всплывающие события

Рассмотрим следующий код:

Вы можете увидеть это более наглядно, когда проанализируете такую разметку:

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

Поведение всплывающих событий позволяет нам делать «делегирование событий» — связывание обработчиков с элементами высокого уровня, а затем определение, какие элементы низкого уровня инициировали событие. Так, мы могли бы связать событие с маркированным списком, а затем выяснить, какой элемент инициировал событие:

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

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

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

Резюме

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

Источник

Продвинутая работа с объектом Event на JavaScript

Учебник JavaScript

Практика

Работа с DOM

Практика

Некоторые продвинутые вещи

Рекомендованное ES6

Некоторые видео могут забегать вперед, тк к этому месту учебника мы прошли еще не весь ES6. Просто пропускайте такие видео, посмотрите потом.

Регулярки

Разное

Работа с канвасом

Практика

Контекст

Drag-and-Drop

Практика по ООП

Ваша задача: посмотрите, попробуйте повторить.

Практика

Promise ES6

Библиотека jQuery

Тк. jQuery устаревает, объявляю эти уроки не обязательными и выношу в конец учебника (так по уровню уроки середины учебника, если что). В перспективе переедет в отдельный учебник по jq.

Сейчас мы с вами разберем некоторые продвинутые вещи при работе с объектом Event, а именно: всплытие и перехват, а также делегирование событий.

Всплытие событий

Представьте себе, что у вас есть несколько вложенных друг в друга блоков:

Когда вы кликаете на самый внутренний блок, событие onclick возникает сначала в нем, а затем срабатывает в его родителе, в родителе его родителя и так далее, пока не дойдет то тега body и далее до тега html (затем до document и до window).

И это логично, ведь кликая на внутренний блок, вы одновременно кликаете на все внешние.

Давайте убедимся в этом на следующем примере: у нас есть 3 блока, к каждому из них привязано событие onclick:

event.target

Пусть у нас есть два элемента: div и абзац p, лежащий внутри этого дива. Пусть onlick мы привязали в диву:

Когда мы кликаем на этот див, мы можем попасть по абзацу, а можем попасть в место, где этого абзаца нет.

Давайте привяжем событие onclick самому верхнему элементу (диву) и будем кликать на разные элементы: на div, на p, на span. С помощью event.target получим самый нижний элемент, в котором случилось событие и выведем его название с помощью tagName.

Прекращение всплытия

Итак, вы уже знаете, что все события всплывают до самого верха (до тега html, а затем до document, а затем до window). Иногда есть нужда это всплытие остановить. Это может сделать любой элемент, через который всплывает событие. Для этого в коде элемента следует вызвать метод event.stopPropagation().

Погружение

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

Вступление к делегированию

Представим себе ситуацию: пусть у нас есть ul с несколькими li. К каждой li привязано следующее событие: по нажатию на li ей в конец добавляется ‘!’.

Давайте реализуем описанное:

Пусть теперь у нас также есть кнопочка, по нажатию на которую в конец ul добавляется новая li с текстом ‘пункт’. Нас ждет сюрприз: привязанное событие не будет работать для новых li! Убедимся в этом:

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

При этом работоспособность нашего скрипта должна сохраниться: по-прежнему при клике на li ей в конец будет добавляться ‘!’. Только событие в новом варианте будет навешано на ul:

Итак, вот решение нашей задачи через делегирование:

Результат выполнения кода:

При этом наше решение будет работать автоматически даже для новых li, ведь событие навешено не на li, а на ul:

Наш код рабочий, однако не без недостатков. Давайте разберем эти недостатки и напишем более универсальное решение.

Универсальное делегирование событий

Недостаток нашего кода проявится в том случае, когда внутри li будут какие-то вложенные теги. В нашем случае пусть это будут теги i:

Проблема исправляется следующим образом (описанный способ не единственный, но самый простой): с помощью метода closest найдем ближайшую li, котоорая является родителем для event.target вот так: event.target.closest(‘li’).

Если же клик был на самой li, то и в event.target, и в event.target.closest(‘li’) будет лежать наша li.

Результат выполнения кода:

Дополнительные материалы

Рекомендую посмотреть тренинг по делегированию событий.

Что вам делать дальше:

Приступайте к решению задач по следующей ссылке: задачи к уроку.

Источник

Еще раз о делегирование или как правильно использовать свои события

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

Для начала вспомним, что же такое делегирование на следующем примере:

В примере есть две ссылки, по клику на которые выполнятся те или иные действия. В данном случае это редактирование и удаление item. Для того, чтоб не добавлять соответствующие слушатели на каждую из ссылок, можно просто добавить один слушатель для контейнера, в котором находятся ссылки и дальше уже по событию получить элемент с которым было связанно это событие. Т.е. в данном примере по клику на одну из ссылок мы получим элемент на который был произведен клик и определим какой из ссылок принадлежит это событие. Кликнув на ссылку ‘Edit’, в консоли выведется сообщение ‘Clicked to edit link’, а для ссылки ‘Delete’ — ‘Clicked to delete link’.

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

В некоторых случаях, может потребоваться использовать структуры контейнеров с множеством вложений. Для простоты понимания, создадим структуру с одним вложением контейнеров:

В проекте, над которым я работаю, мне потребовалось использовать собственные события. Каждый из контейнеров имел свое событие, но оно именовалось одинаково для обоих. Но сам не подозревая того, я применил делегирование к структуре с вложенными контейнерами. Для наглядности, я вынес все в небольшой пример, который мы и рассмотрим.

В этом примере мы просто добавляем слушателя родительскому контейнеру и отслеживаем событие ‘some_event’. То же самое делаем и для вложенного контейнера ‘subcontainer’. Если в данный момент вызвать триггер для вложенного контейнера, то в консоли у нас выведется:

worked event for container
worked event for subcontainer

Если честно, когда я добавлял, у себя в проекте слушателей для одинаковых событий, к подобной структуре, то я такого результата не ожидал. События у меня именовались одинаково, да вот тока выполняли совсем разные действия. Когда код такой вот небольшой, то ошибку можно найти сразу, а если это все находится в классах по несколько 100 строк, то очень такие не просто отследить не правильный код. Чтоб избежать ошибки в выполнении, лучше всегда использовать namespaces.

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

Источник

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

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