Должны ли все события jquery быть привязаны к $ (документу)?
Где это происходит
Когда я впервые узнал jQuery, я обычно добавлял такие события:
$('.my-widget a').click(function() { $(this).toggleClass('active'); });
Узнав больше о скорости выбора и делегировании событий, я прочитал в нескольких местах, что «делегирование события jQuery сделает ваш код быстрее». Поэтому я начал писать код следующим образом:
$('.my-widget').on('click','a',function() { $(this).toggleClass('active'); });
Это был также рекомендуемый способ воспроизвести поведение устаревшего события .live (). Что важно для меня, так как многие мои сайты постоянно добавляют / удаляют виджетов. Вышеизложенное не ведет себя точно так же, как .live (), поскольку только элементы, добавленные в уже существующий контейнер «.my-widget», получат поведение. Если я динамически добавлю еще один блок html после запуска этого кода, эти элементы не получат связанных с ними событий. Как это:
- Как я могу определить, возвращает ли селектор null?
- jQuery как найти элемент на основе значения атрибута данных?
- addID в jQuery?
- jQuery .bind () vs. .on ()
- Выбор индекса jQuery
setTimeout(function() { $('body').append('
'); }, 1000);
Чего я хочу достичь:
- старое поведение .live () // означает добавление событий к еще не существующим элементам
- преимущества .on ()
- максимальная производительность для привязки событий
- Простой способ управления событиями
Теперь я присоединяю все следующие события:
$(document).on('click.my-widget-namespace', '.my-widget a', function() { $(this).toggleClass('active'); });
Который, кажется, отвечает всем моим целям. (Да, по какой-то причине он медленнее в IE, не знаю, почему?) Это быстро, потому что только одно событие привязано к сингулярному элементу, а вторичный селектор оценивается только тогда, когда происходит событие (пожалуйста, исправьте меня, если это не так). Пространство имен является удивительным, поскольку упрощает переключение прослушивателя событий.
Мое решение / вопрос
Поэтому я начинаю думать, что события jQuery всегда должны быть привязаны к $ (документу).
Есть ли причина, по которой вы не хотели бы этого делать?
Можно ли считать это лучшей практикой? Если нет, то почему?
Если вы прочитали все это, спасибо. Я ценю любые / все отзывы / идеи.
Предположения:
- Использование jQuery, поддерживающего
.on()
// по крайней мере версию 1.7 - Вы хотите, чтобы событие добавлялось к динамически добавленному контенту
Показания / Примеры:
- http://24ways.org/2011/your-jquery-now-with-less-suck
- http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery
- http://www.jasonbuckboyer.com/playground/speed/speed.html
- http://api.jquery.com/on/
- Есть ли jQuery-подобный CSS / HTML-селектор, который можно использовать в C #?
- jQuery выбрать по classу VS выбрать по атрибуту
- Селектор jQuery: Id заканчивается?
- Имя атрибута jQuery содержит
- jQuery получить все div, которые не имеют атрибута classа
- Изменение CSS-элемента дочернего элемента при зависании родительского элемента
- Какие селектора CSS3 действительно поддерживают jQuery, например: nth-last-child ()?
- jQuery mobile - для каждого события прямого трансляционного события должно существовать эквивалентное событие click?
Нет – вы НЕ должны привязывать все делегированные обработчики событий к объекту document
. Вероятно, это худший сценарий, который вы могли бы создать.
Во-первых, делегирование событий не всегда делает ваш код быстрее. В некоторых случаях это выгодно, а в некоторых случаях и нет. Вы должны использовать делегирование событий, когда вам действительно нужно делегирование событий, и когда вам это выгодно. В противном случае вы должны привязать обработчики событий непосредственно к объектам, где происходит событие, поскольку это, как правило, будет более эффективным.
Во-вторых, вы НЕ должны связывать все делегированные события на уровне документа. Именно поэтому .live()
устарел, потому что это очень неэффективно, когда у вас много событий, связанных таким образом. Для делегированной обработки событий намного эффективнее связывать их с ближайшим родителем, который не является динамическим.
В-третьих, не все события работают или все проблемы могут быть решены с помощью делегирования. Например, если вы хотите перехватить ключевые события на элементе управления ввода и заблокировать недействительные ключи от ввода в элемент управления ввода, вы не сможете сделать это с помощью делегированной обработки событий, поскольку к моменту, когда событие пузырится до делегированного обработчика, оно уже были обработаны входным контролем, и слишком поздно влиять на это поведение.
Здесь время, когда делегирование событий требуется или выгодно:
- Когда объекты, в которые вы записываете события, динамически создаются / удаляются, и вы все равно хотите записывать на них события без необходимости явного перекомпоновки обработчиков событий при каждом создании нового.
- Когда у вас много объектов, которые все хотят одного и того же обработчика событий (где лоты по меньшей мере сотни). В этом случае во время установки может быть более эффективным связывать один делегированный обработчик событий, а не сотни или более прямых обработчиков событий. Обратите внимание, что делегированная обработка событий всегда менее эффективна во время выполнения, чем обработчики прямых событий.
- Когда вы пытаетесь захватить (на более высоком уровне в документе) события, которые происходят на любом элементе документа.
- Когда ваш проект явно использует событие bubbling и stopPropagation (), чтобы решить некоторые проблемы или функции на вашей странице.
Чтобы понять это немного, нужно понять, как работают jQuery делегированные обработчики событий. Когда вы вызываете что-то вроде этого:
$("#myParent").on('click', 'button.actionButton', myFn);
Он устанавливает общий обработчик событий jQuery на объект #myParent
. Когда событие кликается до этого делегированного обработчика событий, jQuery должен пройти список делегированных обработчиков событий, прикрепленных к этому объекту, и посмотреть, соответствует ли исходный элемент для события любому из селекторов в делегированных обработчиках событий.
Поскольку селекторы могут быть довольно вовлечены, это означает, что jQuery должен анализировать каждый селектор, а затем сравнивать его с характеристиками исходной цели события, чтобы убедиться, что он соответствует каждому селектору. Это не дешевая операция. Это не имеет большого значения, если есть только один из них, но если вы поместили все свои селекторы в объект документа и были сотни селекторов, которые бы сравнивались со всеми отдельными событиями с пузырьками, это может серьезно зависеть от производительности обработки событий.
По этой причине вы хотите настроить делегированные обработчики событий, чтобы делегированный обработчик событий был как можно ближе к целевому объекту. Это означает, что при каждом делегированном обработчике событий будет происходить меньшее количество событий, что улучшит производительность. Помещение всех делегированных событий в объект документа является наихудшей возможной производительностью, потому что все пузырящиеся события должны пройти через все делегированные обработчики событий и получить оценку от всех возможных делегированных селекторов событий. Именно поэтому .live()
устарел, потому что это то, что .live()
, и это оказалось очень неэффективным.
Таким образом, для достижения оптимальной производительности:
- Используйте только делегированную обработку событий, когда она действительно предоставляет необходимую вам функцию или повышает производительность. Не всегда используйте его, потому что это легко, потому что, когда вам это действительно не нужно. Это на самом деле хуже работает во время отправки события, чем привязка прямого события.
- Прикрепите делегированные обработчики событий к ближайшему родителю к источнику события, насколько это возможно. Если вы используете делегированную обработку событий, потому что у вас есть динамические элементы, для которых вы хотите захватить события, а затем выберите ближайшего родителя, который сам по себе не является динамическим.
- Используйте простые в использовании селектора для делегированных обработчиков событий. Если вы следовали за тем, как работает делегированная обработка событий, вы поймете, что делегированный обработчик событий нужно сравнивать с большим количеством объектов много раз, поэтому вы выбираете как можно эффективный селектор или добавляете простые classы к своим объектам, поэтому более простые селектора могут использоваться повысить эффективность делегированной обработки событий.
Делегирование событий – это метод написания обработчиков до того, как элемент действительно существует в DOM. Этот метод имеет свои недостатки и должен использоваться только в том случае, если у вас есть такие требования.
Когда вы должны использовать делегирование событий?
- Когда вы связываете общий обработчик для большего количества элементов, которые нуждаются в такой же функциональности. (Пример: наведение строки в таблице)
- В примере, если вам пришлось связывать все строки с помощью прямого связывания, вы должны создать n обработчик для n строк в этой таблице. Используя метод делегирования, вы можете обрабатывать все те, которые находятся в одном простом обработчике.
- Когда вы добавляете динамическое содержимое чаще в DOM (например: добавление / удаление строк из таблицы)
Почему вы не должны использовать делегирование событий?
- Делегирование событий медленнее по сравнению с привязкой события непосредственно к элементу.
- Он сравнивает целевой селектор на каждом попадании пузыря, сравнение будет таким же дорогостоящим, как и сложным.
- Никакой контроль над событием пузырится до тех пор, пока он не ударит по элементу, к которому он привязан.
PS: Даже для динамического содержимого вам не нужно использовать метод делегирования событий, если вы привязываете обработчик после того, как содержимое вставлено в DOM. (Если динамический контент добавляется не часто удаляется / повторно добавляется)