Я хотел бы добавить некоторые замечания и контраргументы к ответу jfriend00. (в основном только мои мнения, основанные на моем чувстве кишки)
Нет - вам НЕ следует связывать все делегированные обработчики событий с объектом документа. Это, вероятно, худший сценарий, который вы могли бы создать.
Во-первых, делегирование событий не всегда делает ваш код быстрее. В некоторых случаях это выгодно, а в некоторых - нет. Вы должны использовать делегирование событий, когда вам действительно нужно делегирование событий и когда вы получаете от этого пользу. В противном случае вы должны привязывать обработчики событий непосредственно к объектам, где происходит событие, поскольку это обычно будет более эффективным.
Хотя это правда, что производительность может быть немного лучше, если вы собираетесь регистрировать и регистрировать только один элемент, я считаю, что это не сравнится с преимуществами масштабируемости, которые дает делегирование. Я также считаю, что браузеры будут (и будут) обрабатывать это все более и более эффективно, хотя у меня нет никаких доказательств этого. На мой взгляд, делегирование событий - это путь!
Во-вторых, вы НЕ должны связывать все делегированные события на уровне документа. Именно поэтому .live () устарела, потому что это очень неэффективно, когда у вас много событий, связанных таким образом. Для делегированной обработки событий НАМНОГО более эффективно связать их с ближайшим родителем, который не является динамическим.
Я вроде согласен с этим. Если вы на 100% уверены, что событие произойдет только внутри контейнера, имеет смысл связать событие с этим контейнером, но я бы все же поспорил с тем, чтобы связывать события с инициирующим элементом напрямую.
В-третьих, не все мероприятия работают или все проблемы могут быть решены с делегированием. Например, если вы хотите перехватить ключевые события в элементе управления вводом и заблокировать ввод недопустимых ключей в элемент управления вводом, вы не сможете сделать это с обработкой делегированных событий, потому что к тому времени, когда событие переходит в делегированный обработчик, оно уже имеет обработан входным управлением, и уже слишком поздно влиять на это поведение.
Это просто неправда. Пожалуйста, смотрите этот codePen: https://codepen.io/pwkip/pen/jObGmjq
document.addEventListener('keypress', (e) => {
e.preventDefault();
});
Он показывает, как вы можете запретить пользователю печатать, зарегистрировав событие нажатия клавиши в документе.
Вот случаи, когда делегирование события требуется или выгодно:
Когда объекты, на которые вы записываете события, динамически создаются / удаляются, и вы все еще хотите захватывать события на них без необходимости явно перепривязывать обработчики событий каждый раз, когда вы создаете новый. Когда у вас много объектов, которым нужен один и тот же обработчик событий (где много, по крайней мере, сотни). В этом случае может быть более эффективным во время установки связать один делегированный обработчик событий, а не сотни или более прямых обработчиков событий.Обратите внимание, что делегированная обработка событий всегда менее эффективна во время выполнения, чем прямые обработчики событий.
Я хотел бы ответить с этой цитатой из https://ehsangazar.com/optimizing-javascript-event-listeners-for-performance-e28406ad406c
Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.
Кроме того, поиск в Google performance cost of event delegation google
возвращает больше результатов в пользу делегирования событий.
Когда вы пытаетесь захватить (на более высоком уровне в вашем документе) события, которые происходят с любым элементом в документе. Когда ваш дизайн явно использует всплывающие события и stopPropagation (), чтобы решить какую-то проблему или функцию на вашей странице. Чтобы понять это немного больше, нужно понять, как работают делегированные обработчики событий jQuery. Когда вы звоните что-то вроде этого:
$ ("# myParent"). on ('click', 'button.actionButton', myFn); Он устанавливает универсальный обработчик событий jQuery на объект #myParent. Когда событие click вспыхивает до этого обработчика делегированных событий, jQuery должен пройти через список обработчиков делегированных событий, прикрепленных к этому объекту, и посмотреть, соответствует ли исходный элемент для события любому из селекторов в обработчиках делегированных событий.
Поскольку селекторы могут быть задействованы, это означает, что jQuery должен проанализировать каждый селектор и затем сравнить его с характеристиками исходного целевого события, чтобы увидеть, соответствует ли он каждому селектору. Это не дешевая операция. Нет ничего страшного, если есть только один из них, но если вы поместите все свои селекторы на объект документа и сотни селекторов будут сравниваться с каждым отдельным всплывающим событием, это может серьезно снизить производительность обработки событий.
По этой причине вы хотите настроить делегированные обработчики событий так, чтобы делегированный обработчик событий был как можно ближе к целевому объекту. Это означает, что через каждый делегированный обработчик событий будет проходить меньше событий, что повышает производительность. Помещение всех делегированных событий в объект документа является наихудшей возможной производительностью, поскольку все всплывающие события должны проходить через все делегированные обработчики событий и оцениваться для всех возможных делегированных селекторов событий. Именно поэтому .live () устарела, потому что именно это .live () сделала, и это оказалось очень неэффективным.
Где это задокументировано? Если это так, то jQuery, похоже, обрабатывает делегирование очень неэффективным образом, и тогда мои контраргументы должны применяться только к vanilla JS.
Тем не менее: я хотел бы найти официальный источник в поддержку этого утверждения.
:: РЕДАКТИРОВАТЬ ::
Похоже, что jQuery действительно делает всплывающее событие очень неэффективным способом (потому что они поддерживают IE8)
https://api.jquery.com/on/#event-performance
Поэтому большинство моих аргументов здесь справедливы только для vanilla JS и современных браузеров.