Я пытаюсь понять эту конкретную разницу между прямыми и делегированных обработчиков событий с помощью JQuery .он () метод . В частности, последнее предложение в этом пункте:
Когда
selector
предоставляется a , обработчик события называется делегированным . Обработчик вызывается не тогда, когда событие происходит непосредственно в связанном элементе, а только для потомков (внутренних элементов), которые соответствуют селектору. jQuery переносит событие от цели события до элемента, к которому прикреплен обработчик (т. е. от самого внутреннего к внешнему элементу), и запускает обработчик для любых элементов на этом пути, соответствующих селектору.
Что означает «запускает обработчик для любых элементов»? Я сделал тестовую страницу, чтобы поэкспериментировать с концепцией. Но обе следующие конструкции ведут к одинаковому поведению:
$("div#target span.green").on("click", function() {
alert($(this).attr("class") + " is clicked");
});
или,
$("div#target").on("click", "span.green", function() {
alert($(this).attr("class") + " is clicked");
});
Может быть, кто-то мог бы обратиться к другому примеру, чтобы прояснить этот момент? Спасибо.
Ответы:
Случай 1 (прямой):
== Эй! Я хочу, чтобы каждый span.green внутри div # target прослушивался: когда вы нажмете, сделайте X.
Дело 2 (делегировано):
== Эй, div # target! Когда любой из ваших дочерних элементов, которые являются "span.green", нажаты, сделайте X с ними.
Другими словами...
В случае 1 каждому из этих промежутков были даны индивидуальные инструкции. Если создаются новые пролеты, они не услышат инструкции и не будут реагировать на клики. Каждый промежуток напрямую отвечает за свои события.
В случае 2 только контейнер был дан инструкции; он отвечает за уведомление о кликах от имени своих дочерних элементов. Работа по отлову событий была делегирована . Это также означает, что инструкция будет выполняться для дочерних элементов, которые будут созданы в будущем.
источник
on()
допускается два аргумента, когда это в значительной степени совпадает с использованиемclick()
?e.target
будет исходной целью события click (может быть дочерним узлом, если уspan.green
него есть дочерние элементы ). Изнутри обработчик, вы должны использоватьthis
ссылку. Смотри эту скрипку .Первый способ,
$("div#target span.green").on()
привязывает обработчик щелчка непосредственно к диапазону (ам), который соответствует селектору в момент выполнения кода. Это означает, что если другие диапазоны будут добавлены позже (или их класс будет изменен для соответствия), они пропустят и не будут иметь обработчика щелчков. Это также означает, что если впоследствии вы удалите «зеленый» класс из одного из диапазонов, его обработчик кликов продолжит работу - jQuery не отслеживает, как был назначен обработчик, и проверяет, совпадает ли селектор.Второй способ,
$("div#target").on()
привязывает обработчик щелчка к соответствующим элементам (ам) (опять же, это относится к тем, которые совпадают в этот момент), но когда щелчок происходит где-то в элементе div, функция обработчика будет запускаться, только если щелчок произошло не только в div, но и в дочернем элементе, который соответствует селектору во втором параметре.on()
, «span.green». Сделано таким образом, не имеет значения, когда были созданы эти дочерние промежутки, щелчок по ним все равно запускает обработчик.Так что для страницы, которая динамически не добавляет и не изменяет свое содержимое, вы не заметите разницы между этими двумя методами. Если вы динамически добавляете дополнительные дочерние элементы, второй синтаксис означает, что вам не нужно беспокоиться о назначении им обработчиков кликов, потому что вы уже сделали это один раз для родительского элемента.
источник
Объяснение N3dst4 идеально. Исходя из этого, мы можем предположить, что все дочерние элементы находятся внутри тела, поэтому нам нужно использовать только это:
Работает с прямым или делегированным событием.
источник
$('body').on()
делегирование от.element
должно вести себя точно так же, как нативноеdocument.body.addEventHandler()
сif (Event.target.className.matches(/\belement\b/))
обратным вызовом. Это может быть немного медленнее в jquery из-за$.proxy
накладных расходов, но не цитируйте меня об этом.Касательно OP, но концепция, которая помогла мне распутать путаницу с этой функцией, заключается в том, что связанные элементы должны быть родителями выбранных элементов .
.on
..on()
.Делегирование не работает как .find (), выбирая подмножество связанных элементов. Селектор применяется только к строгим дочерним элементам.
сильно отличается от
В частности, чтобы получить преимущества, на которые намекает @ N3dst4 с «элементами, которые будут созданы в будущем», связанный элемент должен быть постоянным родителем . Тогда выбранные дети могут приходить и уходить.
РЕДАКТИРОВАТЬ
Контрольный список того, почему делегирование
.on
не работаетХитрые причины, почему
$('.bound').on('event', '.selected', some_function)
не может работать:.on()
.stopPropagation()
.(Опуская менее хитрые причины, такие как селектор с ошибкой.)
источник
Я написал пост со сравнением прямых и делегированных событий. Я сравниваю чистый js, но он имеет то же значение для jquery, которое только инкапсулирует его.
Вывод заключается в том, что делегированная обработка событий предназначена для динамической структуры DOM, в которой можно создавать связанные элементы, пока пользователь взаимодействует со страницей (повторные привязки не нужны), а прямая обработка событий предназначена для статических элементов DOM, когда мы знаем, что структура не изменится.
Для получения дополнительной информации и полного сравнения - http://maciejsikora.com/standard-events-vs-event-delegation/
Использование всегда делегированных обработчиков, что, на мой взгляд, в настоящее время очень модно, является неправильным способом, многие программисты используют его, потому что «его следует использовать», но правда в том, что прямые обработчики событий лучше в некоторых ситуациях, и выбор, какой метод использовать, должен поддерживаться. знанием различий.
источник