Задать вопрос

Приведенный мною код — одно и то же? Или один работет быстрее / эффективнее, а другой — нет?

Вот первый вариант:
$(document).on('click', function(e) {
	if ($(e.target).hasClass('button')) {...}
});

Вот второй вариант:
$(document).on('click', '.button', function() {...});


Оба кода делают то же самое. Но я хочу узнать - с точки зрения эффективности (скорости, ресурсов) они также одинаковы? Просто когда жму Event Listeners в chrome - там у каждого элемента оочень много listener'ов. Хочу сократить их.
  • Вопрос задан
  • 908 просмотров
Подписаться 7 Простой 4 комментария
Решения вопроса 1
Exploding
@Exploding
wtf?
Гггг))) Как бы с первого взгляда и одно и то же, но не совсем.
Если первый вариант юзать на практике - далеко не всегда ваш ".button" будет совпадать с тем, что находится в таргете. Например на кнопке иконка/рисунок/etc. Поэтому вам придется дописывать специализированный костылеподобный изворот типа:
if ($(e.target).closest('.button').length){
	//....
	e.stopPropagation();
}

что само по себе уже не совсем тоже самое, как предпогалолась в вопросе.
К тому же, не будет возможности использовать .trigger() для .button
Ну и не известно сколько еще потом по вылазит глюков, требующих, чтоб и их подперли чем-то...
В итоге получится явно не быстрее и не стабильней чем в либе. Там как ни как сидят, почесывая башни изо дня в день, думая как еще оптимизировать и стабилизировать работу методов. Версий то вон уже сколько вышло.

UPD
Просто когда жму Event Listeners в chrome - там у каждого элемента оочень много listener'ов

Во втором варианте слушатель вешается не на кнопку, а на документ. Видимо у вас просто установлен чекбокс на "Ancestors".

Ну а если вам взбредет в голову все таки писать свою реализацию делегирования, то в лучшем случае, как мне кажется, вы придёте к оригинальной реализации метода jq.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
rockon404
@rockon404
Frontend Developer
Да нет особой разницы. Накидал бенчмарк для трех вариантов делегирования:

p0:
$('.wrapper').on('click', '.btn', function() { 
  //handler 
});


p1:
$('.wrapper').on('click', function(e) {
  if ($(e.target).hasClass('btn')) {
    //handler 
  }
});


p2:
document.querySelector('.wrapper').addEventListener('click', function(e) {
  if(e.target && e.target.classList.contains('btn')) {
     //handler 
  }
});


Результат для каждого это доли от одной тысячной секунды.

Смело используйте самый удобный для конкретного случая вариант.

Вариант с условием p1 подойдет для объединения слушателей нескольких элементов(например все кликабельные элементы карточки товара). Так быстрей пройдет инициализация и потребуется меньше памяти. Другое дело, что операции сравнения тоже не дешевые и один GodEventHandler тоже делать не стоит.

Так же если у кнопки есть дочерние элементы, то тут лучше использовать вариант p0 , так как он определяет целевой элемент как e.curentTarget, дочерний элемент клика как e.target и делегата на котором будет слушать событие как e.delegateTarget и сработает точно про клику по целевому элементу или его детям. В случаях p1 и p2 клик по дочернему элементу пройдет мимо условий, так как e.target будет дочерним элементом, а не целевым.

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

Войдите, чтобы написать ответ

Похожие вопросы