Что делает делегирование по сравнению с простым ('click', ...)? - PullRequest
4 голосов
/ 14 ноября 2011

Чем отличаются производительность и обработка этих двух различных операторов jQuery:

  1. Number One :

    $('#selector1, #selector2, .class1').on('click', function () { 
         //stuff
    });
    
  2. Номер два :

    $(document).on('click', '#selector1, #selector2, .class1', function () { 
         //stuff
    });
    

Я знаю, что один делегирует, а другой нет.

Но что это значит?

Не оба ли выполняют какое-то действие, когда вы нажимаете '#selector1, #selector2, .class1'?

В конце концов, не так ли?то же самое?

Ответы [ 4 ]

8 голосов
/ 14 ноября 2011

Number One подключит событие click к элементам, которые существуют при выполнении этого оператора.Например, обработчик напрямую подключается к фактическим элементам, которые совпадают, когда вы выполняете этот вызов.

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

Это означает несколько вещей:

  1. Используя номер два, нажимает на элементы, которые вы добавляете позже вызовет обработчик;с номером один они не будут.
  2. Только второстепенные события, такие как click, работают с номером два (потому что он основан на событии, поднимающем DOM до уровня документа).
  3. Если выиспользуйте делегированный обработчик (номер два), а другой код перехватывает событие для фактического элемента, а затем отменяет распространение (всплывающее) событие, делегированный обработчик его не видит.
  4. делегированная форма (числоДва) должен сопоставить элемент, который был нажат (и, возможно, его предки), с селектором, когда происходит щелчок, который занимает ненулевое количество времени.Не обязательно много времени, но больше, чем прямой обработчик (который не должен этого делать).Если у вас много делегированных обработчиков в одном и том же элементе (в данном случае в документе), вы можете начать замечать.

Бывают случаи, когда использование обработчика с прямой перехваткой лучше, а иногдакогда делегирование событий (обычно с использованием чего-то более сфокусированного, чем document) лучше.Обычно разделительная линия между ними является оценочным вызовом, но, например, если вы хотите реагировать на щелчки по строкам таблицы, вам, вероятно, лучше перехватить событие click для элемента table с помощью селектора trвместо того, чтобы прикреплять событие click каждой строки таблицы, особенно если вы динамически обновляете таблицу.Если у вас есть уникальная кнопка, которая, как вы знаете, существует в DOM, когда вы подключаете свой обработчик, и вы хотите запустить определенную функцию, когда нажимается эта кнопка (но не что-нибудь еще), прямой обработчик, вероятно, имеет больше смысла.

Вот пример ( живая копия ):

HTML:

<p>Click me</p>

JavaScript:

jQuery(function($) {

  $('p').on('click', function() {
    display("Directly-attached handler fired. Click this paragraph and note the difference in what happens compared to when you click the 'click me' paragraph.");
  });
  $(document).on('click', 'p', function() {
    display("Delegated handler fired.");
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }
});

Обратите внимание, чтопри нажатии на абзац «щелкни меня» к документу добавляются два новых абзаца, один из которых является результатом первого вызова on, а другой - вторым.Но обратите внимание, что если вы щелкнете по любому из этих двух новых абзацев, вы только увидите обработчик из второго on вызова ( делегированный один), а не из первого.Это потому, что эти абзацы не существовали, когда вы подключили первый обработчик.

5 голосов
/ 14 ноября 2011
  1. Метод on() присоединяет обработчик событий для каждого из элементов, соответствующих объекту jQuery.Если вы передадите необязательный селектор методу on(), обработчик сработает только в том случае, если событие произошло в потомке этого элемента.

    В связи с этим в первом примере будут прикреплены несколько обработчиков событий, поскольку объект jQuery содержит 3 элемента.Однако во втором примере будет прикреплен один обработчик событий, который будет обрабатывать событие click для всех *1000*

    . Очевидно, что это оставляет первый недостаток производительности, если сопоставлено много элементов (как несколько обработчиков событий).связаны, по сравнению с единственным, прикрепленным во втором примере).

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

  2. Потому чтоon() присоединяет обработчики к каждому из элементов, соответствующих объекту jQuery, вы не можете прикреплять обработчики напрямую к элементам, которых еще нет в DOM (например, если вы хотите добавить элементы программно через код или через AJAX).Именно здесь возможность предоставить селектор в качестве параметра для on() становится чрезвычайно полезной;это позволяет вам присоединить обработчик событий к элементу, который в данный момент находится в DOM, но который будет обрабатывать события, которые запускаются для элементов, которые еще не в DOM (но которые соответствуют выбранному вами селектору).

    Другими словами, в первом примере jQuery присоединяет обработчик событий ко всем элементам, которые соответствуют селектору #selector1, #selector2, .class1;и поэтому пропустит все элементы, которые еще не были зарегистрированы в DOM.

    С другой стороны, если вы используете второй пример, jQuery присоединяет обработчик событий ко всем элементам, которые соответствуют селектору document(например, одиночный элемент Document) и присоединяет к нему обработчик, который сработает, если полученное событие произошло из элемента, соответствующего селектору #selector1, #selector2, .class1;это имеет преимущество работы для всех будущих #selector1, #selector2, .class1 элементов.

    Вы можете увидеть это в действии здесь;http://jsfiddle.net/kntR7/

  3. Поскольку номер два связан с document, любой элемент, который принимает обработчик для того же события, получит обработчик раньше (так как document - последнее место, которое получаетобработчик через распространение события), поэтому, если он решит отменить событие, используя event.stopPropagation() или event.stopImmediatePropagation(), обработчик никогда не будет достигнут.

    Вы можете увидеть это в действии здесь;http://jsfiddle.net/mkNyU/

1 голос
/ 14 ноября 2011

Для тех, кто знаком с синтаксисом до 1.7, вот как можно использовать on:

//bind syntax
$(selector).on(event, callback);
$(selector).bind(event, callback);

//delegate syntax
$(parent).on(event, selector, callback);
$(selector).delegate(selector, event, callback);

//live syntax
$(document).on(event, selector, callback);
$(selector).live(event, callback);

Итак, ваша первая строка ($('#selector1, #selector2, .class1').on('click', function)) - это формат bind для присоединения событий к существующимelements.

Ваша вторая строка ($(document).on('click', '#selector1, #selector2, .class1', function)) имеет формат live, чтобы прикреплять события к любому элементу, который соответствует селектору, когда происходит событие, независимо от того, существуют ли элементы в dom во времяпереплет.

0 голосов
/ 14 ноября 2011

Первый связывает 3+ обработчиков событий (по одному на каждый элемент), которые теряются при замене элементов.Первый из них потерпит неудачу, если элементы еще не существуют.

Второй связывает 1 обработчик события (один с document), который никогда не будет потерян, если вы явно не удалите его.И как только здесь вызывается обработчик, событие уже распространилось до document.Каждый раз, когда вы щелкаете в любом месте страницы, jQuery внутренне проверяет, был ли он на каком-либо элементе, который соответствует заданному вами селектору, и запускает обработчик, который вы дали, если это так.Это только в том случае, если событие распространяется на document и не было остановлено на элементе более низкого уровня.

Второе может быть связано даже до готовности документа, и оно все равно будет работать, даже если элементы этого не делаютсуществует еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...