Ответ 1
Нет - вы НЕ должны привязывать все делегированные обработчики событий к объекту document
. Вероятно, это самый худший сценарий, который вы могли бы создать.
Во-первых, делегирование событий не всегда делает ваш код быстрее. В некоторых случаях это выгодно, а в некоторых случаях и нет. Вы должны использовать делегирование событий, когда вам действительно нужно делегирование событий, и когда вам это выгодно. В противном случае вы должны привязать обработчики событий непосредственно к объектам, где происходит событие, поскольку это, как правило, будет более эффективным.
Во-вторых, вы НЕ должны привязывать все делегированные события на уровне документа. Именно поэтому .live()
был устаревшим, потому что это очень неэффективно, когда у вас много событий, связанных таким образом. Для делегированной обработки событий намного эффективнее связывать их с ближайшим родителем, который не является динамическим.
В-третьих, не все события работают или все проблемы могут быть решены с помощью делегирования. Например, если вы хотите перехватить ключевые события на элементе управления ввода и заблокировать недействительные ключи от ввода в элемент управления ввода, вы не сможете сделать это с помощью делегированной обработки событий, поскольку к моменту, когда событие пузырится до делегированного обработчика, оно уже был обработан элементом управления вводом, и он слишком поздно, чтобы повлиять на это поведение.
Здесь время, когда делегирование событий требуется или выгодно:
- Когда объекты, в которые вы записываете события, динамически создаются/удаляются, и вы все равно хотите записывать на них события, не переустанавливая обработчики событий каждый раз при создании нового.
- Когда у вас есть много объектов, которые все хотят точно такого же обработчика событий (где лоты по меньшей мере сотни). В этом случае во время установки может быть более эффективным связывать один делегированный обработчик событий, а не сотни или более прямых обработчиков событий. Обратите внимание: делегированная обработка событий всегда менее эффективна во время выполнения, чем прямые обработчики событий.
- Когда вы пытаетесь захватить (на более высоком уровне в документе) события, которые происходят на любом элементе документа.
- Когда ваш проект явно использует событие bubbling и stopPropagation(), чтобы решить некоторые проблемы или функции на вашей странице.
Чтобы понять это немного, нужно понять, как работают обработчики jQuery делегированных обработчиков событий. Когда вы вызываете что-то вроде этого:
$("#myParent").on('click', 'button.actionButton', myFn);
Он устанавливает общий обработчик событий jQuery в объекте #myParent
. Когда событие кликается до этого делегированного обработчика событий, jQuery должен пройти список делегированных обработчиков событий, прикрепленных к этому объекту, и посмотреть, соответствует ли исходный элемент для события любому из селекторов в делегированных обработчиках событий.
Поскольку селекторы могут быть довольно вовлечены, это означает, что jQuery должен анализировать каждый селектор, а затем сравнивать его с характеристиками исходной цели события, чтобы увидеть, соответствует ли он каждому селектору. Это не дешевая операция. Это не имеет большого значения, если есть только один из них, но если вы поместили все свои селекторы в объект документа и были сотни селекторов, которые бы сравнивались с каждым событием с пузырьками, это может серьезно зависнуть от производительности обработки событий.
По этой причине вы хотите настроить делегированные обработчики событий, чтобы делегированный обработчик событий был как можно ближе к целевому объекту. Это означает, что при каждом делегированном обработчике событий будет происходить меньшее количество событий, что улучшит производительность. Помещение всех делегированных событий в объект документа является наихудшей возможной производительностью, потому что все пузырящиеся события должны пройти через все делегированные обработчики событий и получить оценку от всех возможных делегированных селекторов событий. Именно поэтому .live()
устарел, потому что это то, что сделал .live()
, и оказалось очень неэффективным.
Итак, для достижения оптимальной производительности:
- Используйте только делегированную обработку событий, когда она действительно предоставляет требуемую функцию или повышает производительность. Не всегда используйте его, потому что это легко, потому что, когда вам это действительно не нужно. Это на самом деле хуже работает во время отправки события, чем привязка прямого события.
- Прикрепите делегированные обработчики событий к ближайшему родителю к источнику события, насколько это возможно. Если вы используете делегированную обработку событий, потому что у вас есть динамические элементы, для которых вы хотите записывать события, затем выберите ближайшего родителя, который сам по себе не является динамическим.
- Используйте простые в использовании селектора для делегированных обработчиков событий. Если вы следовали за тем, как работает делегированная обработка событий, вы поймете, что делегированный обработчик событий нужно сравнивать с большим количеством объектов много раз, поэтому вы выбираете как можно эффективный селектор или добавляете простые классы к своим объектам, поэтому более простые селектора могут использоваться повысить производительность делегированной обработки событий.