This is the 20th day of my participation in the August Text Challenge.More challenges in August

There is an unordered list ul containing three Li’s. When each li is clicked, the contents in the alert will be realized.

<ul id="list">
     <li>1</li>
     <li>2</li>
     <li>3</li>
</ul>
Copy the code

The first thing that comes to mind is:

  var ndItem = document.getElementsByTagName('li');
Copy the code
for(var i=0; i<3; i++){ ndItem[i].addEventListener('click', function () { alert(i); }); }Copy the code

So what if the number of Li’s changed, instead of 3, to 300? If we continue with the above approach, the DOM registered listening events will be 100 times as large, which is obviously not appropriate, and event delegation will solve this problem.

Event delegate, also called event delegate, is described in this way in Js advanced: Event delegate uses event bubble, only specify an event handler, you can manage all events of a certain type.

The DOM event flow consists of three phases: event capture phase -> In target phase -> event bubbling phase.

IE’s event stream is called event bubbling, where events are initially received by the most specific element and gradually propagated up to less specific nodes.

Event capture: Less specific nodes should receive events earlier, while specific nodes receive events last.

)

Implement the above example with event delegate:

Document.getelementbyid ("list").addeventListener ('click', function(e){alert(' + e.target.innertext '); })Copy the code

Here with the parent ul do event processing, due to the principle of bubble, when li was click events will bubble to the ul, click event because ul, so events can trigger, of course, here when clicking the ul also triggers, so the question becomes, ‘if I want to make the effect of the event agency like directly to the node event effect to do, For example, it will only trigger if you click on Li. Read on:

The Event object provides an attribute called target, which returns the target node of the Event, and we become the Event source. That is, target can be represented as the DOM of the current Event operation, but not the DOM of the actual operation. Of course, this is compatible. IE uses event. SrcElement to retrieve the location of the current node, but does not know what the nodeName is. Here we use nodeName to retrieve the name of the node.

Window.onload = function(){var oUl = document.getelementById ("list"); OUl. Onclick = function (ev) {var ev = ev | | window. The event; Var target = ev. Target | | ev. The srcElement; If (target. The nodeName. ToLowerCase () = = 'li') {alert (target. InnerHTML); }}}Copy the code

As above, only clicking on Li will trigger the event, and only one DOM operation will be performed at a time. If the number of Li is large, the DOM operation will be greatly reduced, and the performance optimization can be imagined!

Or, for example, I’ve changed the topic:

<div id="box"> <input type="button" id="add" value=" add" /> <input type="button" id="remove" value=" delete "/> <input <input type="button" id=" button" id="select" value=" select" /> </div>Copy the code

You can also use event delegates:

window.onload = function(){ var oBox = document.getElementById("box"); oBox.onclick = function (ev) { var ev = ev || window.event; var target = ev.target || ev.srcElement; If (target. The nodeName. ToLocaleLowerCase () = = 'input') {switch (target. Id) {case 'add' : alert (' add '); break; Case 'remove' : alert(' delete '); break; Case 'move' : alert(' move'); break; Case 'select' : alert(' select'); break; }}}}Copy the code

For example, if you have a scenario like the following, you can manually add a new LI

< input type = "button" name = "" id =" BTN "value =" add "/ > < ul id =" ul1 "> < li > 111 < / li > < li > 222 < / li > < li > 333 < / li > < li > 444 < / li > </ul>Copy the code

Initial method:

window.onload = function(){ var oBtn = document.getElementById("btn"); var oUl = document.getElementById("ul1"); var aLi = oUl.getElementsByTagName('li'); var num = 4; For (var I =0; i<aLi.length; i++){ aLi[i].onmouseover = function(){ this.style.background = 'red'; }; aLi[i].onmouseout = function(){ this.style.background = '#fff'; Obtn.onclick = function(){num++; var oLi = document.createElement('li'); oLi.innerHTML = 111*num; oUl.appendChild(oLi); }; }Copy the code

If the event is not added, you can optimize it by using event delegate:

window.onload = function(){ var oBtn = document.getElementById("btn"); var oUl = document.getElementById("ul1"); var aLi = oUl.getElementsByTagName('li'); var num = 4; / / events, add child elements also have events oUl. Onmouseover = function (ev) {var ev = ev | | window. The event; var target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase() == 'li'){ target.style.background = "red"; }}; oUl.onmouseout = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase() == 'li'){ target.style.background = "#fff"; }}; Obtn.onclick = function(){num++; var oLi = document.createElement('li'); oLi.innerHTML = 111*num; oUl.appendChild(oLi); }; }Copy the code

Finally, to summarize the events that apply to event delegation are: Click, MouseDown, Mouseup, KeyDown, KeyUp, and keyPress.

It’s worth noting that mouseover and Mouseout events also bubble up, but they’re not as easy to handle and often require calculating element positions.