Что такое делегирование событий DOM? - программирование

Что такое делегирование событий DOM?

Может кто-нибудь объяснить делегирование событий в JavaScript и как это полезно?

4b9b3361

Ответ 1

Делегирование событий DOM - это механизм реагирования на события пользовательского интерфейса через одного общего родителя, а не каждого потомка, с помощью магии "пузырящихся" событий (также называемых распространением событий).

Когда событие инициируется в элементе, происходит следующее:

Событие отправлено к его цели EventTarget и любые слушатели событий нашел там сработало. кипение события будут вызывать любые дополнительные слушатели событий найдены после родителя EventTarget цепь вверх, проверка на любое событие слушатели зарегистрированы на каждом последующий EventTarget. Это вверх распространение будет продолжаться до и включая Document.

Пузырьки событий обеспечивают основу для делегирования событий в браузерах. Теперь вы можете привязать обработчик события к одному родительскому элементу, и этот обработчик будет выполняться всякий раз, когда событие происходит на любом из его дочерних узлов (и, в свою очередь, на любом из их дочерних узлов). Это делегирование события. Вот пример этого на практике:

<ul onclick="alert(event.type + '!')">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
</ul>

В этом примере, если вы щелкнете по любому из дочерних узлов <li>, вы увидите предупреждение "click!", даже если нет обработчика щелчка, связанного с <li>, по которому вы щелкнули. Если мы свяжем onclick="..." с каждым <li>, вы получите тот же эффект.

Так в чем выгода?

Представьте, что вам теперь нужно динамически добавлять новые элементы <li> в приведенный выше список с помощью манипуляций с DOM:

var newLi = document.createElement('li');
newLi.innerHTML = 'Four';
myUL.appendChild(newLi);

Без использования делегирования события вам придется "перепривязать" обработчик событий "onclick" к новому элементу <li>, чтобы он действовал так же, как и его родные братья. С делегированием событий вам не нужно ничего делать. Просто добавьте новый <li> в список, и все готово.

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

Еще одним преимуществом делегирования событий является то, что общий объем памяти, используемый прослушивателями событий, уменьшается (поскольку количество привязок событий уменьшается). Это может не иметь большого значения для маленьких страниц, которые часто выгружаются (то есть пользователь часто переходит на разные страницы). Но для долгоживущих приложений это может быть значительным. Есть некоторые действительно трудные для отслеживания ситуации, когда элементы, удаленные из DOM, все еще требуют памяти (то есть они просачиваются), и часто эта утечка памяти привязана к привязке события. С делегированием событий вы можете уничтожать дочерние элементы, не рискуя забыть "отсоединить" их слушателей событий (так как слушатель находится на предке). Эти типы утечек памяти могут тогда быть сдержаны (если не устранены, что иногда ужасно трудно сделать. IE, я смотрю на Вас).

Вот несколько лучших конкретных примеров кода делегирования событий:

Ответ 2

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

Пример JavaScript:

Скажем, что у нас есть родительский элемент UL с несколькими дочерними элементами:

<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>

Предположим также, что что-то должно произойти при щелчке каждого дочернего элемента. Вы можете добавить отдельный прослушиватель событий для каждого отдельного элемента LI, но что, если элементы LI часто добавляются и удаляются из списка? Добавление и удаление прослушивателей событий было бы кошмаром, особенно если код добавления и удаления находится в разных местах вашего приложения. Лучшее решение - добавить прослушиватель событий в родительский элемент UL. Но если вы добавите прослушиватель событий в родительский элемент, как вы узнаете, какой элемент был нажат?

Простой: когда событие пузырится до элемента UL, вы проверяете свойство target object, чтобы получить ссылку на фактический щелчок node. Вот очень простой фрагмент JavaScript, который иллюстрирует делегирование событий:

// Get the element, add a click listener...
document.getElementById("parent-list").addEventListener("click", function(e) {
// e.target is the clicked element!
// If it was a list item
if(e.target && e.target.nodeName == "LI") {
    // List item found!  Output the ID!
    console.log("List item ", e.target.id.replace("post-"), " was clicked!");
       }
 });

Начните с добавления прослушивателя событий щелчка к родительскому элементу. Когда прослушиватель событий запускается, проверьте элемент события, чтобы убедиться, что он реагирует на тип элемента. Если это элемент LI, бум: у нас есть то, что нам нужно! Если это не тот элемент, который мы хотим, событие можно игнорировать. Этот пример довольно прост - UL и LI - прямое сравнение. Попробуй что-нибудь более сложное. Пусть у родителя DIV много детей, но все, о чем мы заботимся, это тег A с классом CSS класса:

  // Get the parent DIV, add click listener...
  document.getElementById("myDiv").addEventListener("click",function(e) {
// e.target was the clicked element
if(e.target && e.target.nodeName == "A") {
    // Get the CSS classes
    var classes = e.target.className.split(" ");
    // Search for the CSS class!
    if(classes) {
        // For every CSS class the element has...
        for(var x = 0; x < classes.length; x++) {
            // If it has the CSS class we want...
            if(classes[x] == "classA") {
                // Bingo!
                console.log("Anchor element clicked!");
                // Now do something here....
            }
        }
    }

  }
});

http://davidwalsh.name/event-delegate

Ответ 3

делеция событий dom - это нечто иное, чем определение компьютерной науки.

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

Ответ 4

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

Обычно говорят: использовать делегирование как альтернативу наследования. Наследование - это хорошая стратегия, когда между родительским и дочерним объектами существуют тесные отношения, однако наследование связывает объекты очень тесно. Часто делегирование является более гибким способом выражения отношений между классами.

Этот шаблон также известен как "прокси-цепочки". Несколько других шаблонов дизайна используют делегирование - от него зависят состояние, стратегия и шаблоны посетителей.

Ответ 5

Концепция делегирования

Если внутри одного родителя много элементов и вы хотите обрабатывать события из них, не привязывайте обработчики к каждому элементу. Вместо этого свяжите единственный обработчик с их родителем и получите дочерний элемент из event.target. Этот сайт предоставляет полезную информацию о том, как реализовать делегирование событий. http://javascript.info/tutorial/event-delegation

Ответ 6

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

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

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

Вот простой пример (намеренно многословно, чтобы дать возможность встроенного объяснения): Обработка щелчка по любому элементу td в таблице контейнера:

// Handle the event on the container
document.getElementById("container").addEventListener("click", function(event) {
    // Find out if the event targeted or bubbled through a 'td' en route to this container element
    var element = event.target;
    var target;
    while (element && !target) {
        if (element.matches("td")) {
            // Found a 'td' within the container!
            target = element;
        } else {
            // Not found
            if (element === this) {
                // We've reached the container, stop
                element = null;
            } else {
                // Go to the next parent in the ancestry
                element = element.parentNode;
            }
        }
    }
    if (target) {
        console.log("You clicked a td: " + target.textContent);
    } else {
        console.log("That wasn't a td in the container table");
    }
});
table {
    border-collapse: collapse;
    border: 1px solid #ddd;
}
th, td {
    padding: 4px;
    border: 1px solid #ddd;
    font-weight: normal;
}
th.rowheader {
    text-align: left;
}
td {
    cursor: pointer;
}
<table id="container">
    <thead>
        <tr>
            <th>Language</th>
            <th>1</th>
            <th>2</th>
            <th>3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th class="rowheader">English</th>
            <td>one</td>
            <td>two</td>
            <td>three</td>
        </tr>
        <tr>
            <th class="rowheader">Español</th>
            <td>uno</td>
            <td>dos</td>
            <td>tres</td>
        </tr>
        <tr>
            <th class="rowheader">Italiano</th>
            <td>uno</td>
            <td>due</td>
            <td>tre</td>
        </tr>
    </tbody>
</table>

Ответ 7

Это в основном то, как делается связь с элементом. .click применяется к текущему DOM, в то время как .on (с использованием делегирования) будет продолжать действовать для новых элементов, добавленных в DOM после сопоставления событий.

Какой из них лучше использовать, я бы сказал, это зависит от случая.

Пример:

<ul id="todo">
   <li>Do 1</li>
   <li>Do 2</li>
   <li>Do 3</li>
   <li>Do 4</li>
</ul>

.Click Event:

$("li").click(function () {
   $(this).remove ();
});

Событие .on:

$("#todo").on("click", "li", function () {
   $(this).remove();
});

Обратите внимание, что я выделил селектор в .on. Я объясню почему.

Предположим, что после этой ассоциации сделаем следующее:

$("#todo").append("<li>Do 5</li>");

Вот где вы заметите разницу.

Если событие было связано с помощью .click, задача 5 не будет подчиняться событию click, и поэтому не будет удалена.

Если он был связан через .on, с отдельным селектором, он будет подчиняться.

Ответ 8

Делегат в С# похож на указатель на функции в C или С++. Использование делегата позволяет программисту инкапсулировать ссылку на метод внутри объекта делегата. Затем объект делегата может быть передан в код, который может вызвать ссылочный метод, без необходимости знать во время компиляции, какой метод будет вызываться.

Смотрите эту ссылку → http://www.akadia.com/services/dotnet_delegates_and_events.html

Ответ 9

При делегировании событий используются две часто пропускаемые функции событий JavaScript: всплывающее окно события и целевой элемент. Когда событие инициируется в элементе, например, щелчком мыши по кнопке, то же событие также запускается для всех предков этих элементов., Этот процесс известен как всплытие событий; событие всплывает от исходного элемента к вершине дерева DOM.

Представьте себе HTML-таблицу с 10 столбцами и 100 строками, в которой вы хотите, чтобы что-то происходило, когда пользователь щелкает ячейку таблицы. Например, мне нужно было сделать каждую ячейку таблицы такого размера редактируемой при нажатии. Добавление обработчиков событий в каждую из 1000 ячеек было бы серьезной проблемой производительности и, возможно, источником утечек памяти при сбое браузера. Вместо этого, используя делегирование событий, вы добавляете только один обработчик событий к элементу таблицы, перехватываете событие click и определяете, какая ячейка была нажата.

Ответ 10

Делегирование мероприятия

Присоедините слушатель события к родительскому элементу, который срабатывает, когда событие происходит в дочернем элементе.

Распространение событий

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

В этом примере событие (onclick) от кнопки передается родительскому абзацу.

$(document).ready(function() {

    $(".spoiler span").hide();

    /* add event onclick on parent (.spoiler) and delegate its event to child (button) */
    $(".spoiler").on( "click", "button", function() {
    
        $(".spoiler button").hide();    
    
        $(".spoiler span").show();
    
    } );

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<p class="spoiler">
    <span>Hello World</span>
    <button>Click Me</button>
</p>