Прямое или делегированное - jQuery .on () - PullRequest
152 голосов
/ 13 ноября 2011

Я пытаюсь понять это конкретное различие между direct и делегированными обработчиками событий, используя jQuery .on () метод ,В частности, последнее предложение в этом абзаце:

Когда предоставляется selector, обработчик события упоминается как делегированный .Обработчик вызывается не тогда, когда событие происходит непосредственно в связанном элементе, а только для потомков (внутренних элементов), которые соответствуют селектору.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");
});

Может быть, кто-то мог бы обратиться к другому примеру, чтобы прояснить этот момент?Спасибо.

Ответы [ 5 ]

363 голосов
/ 13 ноября 2011

Случай 1 (прямой):

$("div#target span.green").on("click", function() {...});

== Эй! Я хочу, чтобы каждый span.green внутри div # target прослушивался: когда вы нажмете, сделайте X.

Дело 2 (делегировано):

$("div#target").on("click", "span.green", function() {...});

== Эй, div # target! Когда щелкнет любой из ваших дочерних элементов, которые являются "span.green", сделайте с ними X.

Другими словами ...

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

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

5 голосов
/ 13 ноября 2011

Первый способ, $("div#target span.green").on(), привязывает обработчик щелчка непосредственно к диапазону (ам), который соответствует селектору в момент выполнения кода. Это означает, что если другие диапазоны будут добавлены позже (или их класс будет изменен, чтобы соответствовать), они пропустили и не будут иметь обработчик щелчка. Это также означает, что если впоследствии вы удалите «зеленый» класс из одного из диапазонов, его обработчик кликов будет продолжать работать - jQuery не отслеживает, как был назначен обработчик, и проверяет, совпадает ли селектор.

Второй способ, $("div#target").on(), привязывает обработчик щелчка к совпадающим элементам (ам), которые совпадают (опять же, с теми, которые совпадают в данный момент), но когда щелчок происходит где-то в элементе div, функция обработчика запускаться только в том случае, если щелчок произошел не только в элементе div, но и в дочернем элементе, который соответствует селектору во втором параметре .on(), "span.green". Сделано так, что не имеет значения, когда были созданы эти дочерние промежутки, щелчок по ним все равно запускает обработчик.

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

4 голосов
/ 25 апреля 2014

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

$('body').on('click', '.element', function(){
    alert('It works!')
});

Работает с прямым или делегированным событием.

2 голосов
/ 27 января 2016

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

  • Граница относится к тому, что осталось от .on.
  • Выбранный относится ко 2-му аргументу .on().

Делегирование не работает как .find (), выбирая подмножество связанных элементов.Селектор применяется только к строгим дочерним элементам.

$("span.green").on("click", ...

очень отличается от

$("span").on("click", ".green", ...

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

РЕДАКТИРОВАТЬ

Контрольный список причин, по которым делегирование .on не работает

Хитрые причины, по которым $('.bound').on('event', '.selected', some_function) может не работать:

  1. Связанный элемент не является постоянным .Он был создан после вызова .on()
  2. Выбранный элемент не является правильным дочерним связанного элемента.Это тот же элемент.
  3. Выбранный элемент предотвратил всплытие события в связанный элемент, вызвав .stopPropagation().

(Опуская менее хитрые причины, такие каккак селектор с ошибкой.)

1 голос
/ 06 сентября 2016

Я написал пост со сравнением прямых событий и делегированных.Я сравниваю чистый js, но он имеет то же значение для jquery, который только инкапсулирует его.

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

Для получения дополнительной информации и полного сравнения - http://maciejsikora.com/standard-events-vs-event-delegation/

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

...