Я хотів би додати деякі зауваження та контраргументи до відповіді jfriend00. (в основному це лише моя думка, заснована на моєму відчутті кишечника)
Ні - НЕ слід прив'язувати всі делеговані обробники подій до об'єкта документа. Це, мабуть, найгірший сценарій, який ви могли створити.
По-перше, делегування подій не завжди робить ваш код швидшим. У деяких випадках це вигідно, а в деяких випадках - ні. Ви повинні використовувати делегацію подій, коли вам дійсно потрібна делегація подій і коли ви отримаєте від неї користь. В іншому випадку слід прив’язати обробників подій безпосередньо до об'єктів, де відбувається подія, оскільки це, як правило, буде більш ефективним.
Хоча це правда, що продуктивність може бути дещо кращою, якщо ви збираєтесь лише зареєструватися та подіяти для одного елемента, я вважаю, що це не відповідає перевагам масштабування, який приносить делегація. Я також вважаю, що браузери (це буде) обробляють це все ефективніше і ефективніше, хоча я не маю доказів цього. На мою думку, делегація подій - це шлях!
По-друге, НЕ слід пов'язувати всі делеговані події на рівні документа. Саме тому .live () був застарілим, оскільки це дуже неефективно, коли у вас багато подій, пов'язаних таким чином. Для обробки делегованих подій набагато ефективніше прив’язувати їх до найближчого батьківського, що не є динамічним.
Я з цим погоджуюся. Якщо ви на 100% впевнені, що подія відбудеться лише всередині контейнера, є сенс прив’язати подію до цього контейнера, але я все одно заперечуватимуть проти подій прив'язки безпосередньо до запускаючого елемента.
По-третє, не всі події працюють або всі проблеми можна вирішити делегуванням. Наприклад, якщо ви хочете перехопити ключові події в керуванні входом і заблокувати недійсні ключі від введення керування входом, ви не можете цього зробити з делегованою обробкою події, оскільки до моменту подія перетворюється на делегований обробник, вона вже має обробляється вхідним керуванням, і надто пізно впливати на таку поведінку.
Це просто неправда. Перегляньте цей кодPen: 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.
Крім того, гугл для performance cost of event delegation google
повернення більше результатів на користь делегації подій.
Коли ви намагаєтеся захопити (на більш високому рівні у вашому документі) події, які відбуваються на будь-якому елементі документа. Коли ваш дизайн явно використовує бульбашку подій та stopPropagation () для вирішення певної проблеми чи функції на вашій сторінці. Щоб зрозуміти це ще трохи, потрібно зрозуміти, як працюють делеговані обробники подій jQuery. Коли ви телефонуєте щось подібне:
$ ("# myParent"). on ('натиснути', 'button.actionButton', myFn); Він встановлює загальний обробник подій jQuery на об’єкті #myParent. Коли подія клацання перетворюється на цей делегований обробник подій, jQuery повинен пройти список делегованих обробників подій, приєднаних до цього об'єкта, і побачити, чи відповідає вихідний елемент події будь-якому із селекторів делегованих обробників подій.
Оскільки селектори можуть бути досить задіяними, це означає, що jQuery повинен проаналізувати кожен селектор, а потім порівняти його з характеристиками вихідної цілі події, щоб побачити, чи відповідає він кожному селектору. Це не дешева операція. Не важливо, якщо є лише одна з них, але якщо ви поставите всіх своїх селекторів на об'єкт документа, і для їх порівняння з кожною повальною подією було сотні селекторів, це може серйозно почати сприймати ефективність обробки подій.
З цієї причини ви хочете налаштувати делеговані обробники подій, щоб делегований обробник подій був наближений до цільового об'єкта, наскільки це практично. Це означає, що через кожний делегований обробник подій буде проводитись менше подій, тим самим покращуючи ефективність. Розміщення всіх делегованих подій на об’єкт документа - це найгірша можлива ефективність, оскільки всі події, що переносяться, мають пройти через всі делеговані обробники подій та отримати оцінку щодо всіх можливих делегованих селекторів подій. Саме тому .live () застаріло, оскільки саме це зробив .live () і виявилося дуже неефективним.
Де це документально зафіксовано? Якщо це правда, то, схоже, jQuery поводиться з делегуванням дуже неефективно, і тоді мої контр-аргументи слід застосовувати лише до ванільної JS.
Все-таки: я хотів би знайти офіційне джерело, яке б підтверджувало це твердження.
:: EDIT ::
Схоже, jQuery справді робить надзвичайно неефективним способом (тому, що вони підтримують IE8)
https://api.jquery.com/on/#event-performance
Тож більшість моїх аргументів справедливі лише для ванільної JS та сучасних браузерів.