When I was working on a project today, I found a comment about event delegation in the project’s comments (PS: although the following code is not the code for event delegation!). , xiaobian as a front-end do three or four years of small rookie, still do not know what the event delegate is, think about shame, deliberately inserted this column in the middle of Vue3. You can also follow my wechat public number, Snail Quanzhan.

Since we can’t talk about event delegation without bubbling, what is event bubbling? Xiaobian specially found such a picture on the Internet

The bubbles below are small, and the bubbles get bigger as you go up. The bubbles in the figure can be thought of as DOM structures in HTML. So what exactly is bubbling? Let’s say I have a structure like this

<div onclick="handleDivClick()">  
    <ul onclick="handleUlClick()">    
        <li onclick="handleLiClick()">The first element</li>    
        <li onclick="handleLiClick()">Second element</li>    
        <li onclick="handleLiClick()">The third element</li>  
    </ul>
</div>
Copy the code

Again, let’s define three corresponding functions

function handleDivClick(){    
    alert('handleDivClick')}function handleUlClick(){    
    alert('handleUlClick')}function handleLiClick(){    
    alert('handleLiClick')}Copy the code

Now, when we click on the li element, in addition to the click function itself, we’re going to execute the ul and div elements, so once we click, it’s going to pop up three times. E.toppropagation () (W3C) and e.ancelbubble = true (IE) are provided in native JS to prevent event bubbles, and the.stop modifier is also provided in Vue.

The following content is reprinted fromwww.cnblogs.com/lauzhishuai…

So what is event delegation? It is also called event broker. In advanced JavaScript programming, event delegate is to manage all events of a certain type by specifying only one event handler using event bubble. So what does that mean? Online you recognize speaking event delegation basically all use the same example, is take the express to explain this phenomenon, I carefully ponder for a moment, this example is appropriate, I will not to think of other examples to explain, we are, I picked over, all seriously what understand the event delegation is a principle:

Three colleagues are expected to receive deliveries on Monday. In order to sign for the delivery, there are two ways: one is three people waiting for the delivery at the door of the company; Two is entrusted to the front MM to sign for. In reality, most of us use delegated solutions (and companies don’t tolerate so many employees standing at the door waiting for delivery). When the front desk MM receives the express, she will judge who the recipient is, and then sign for it according to the recipient’s requirements, or even pay for it. Another advantage of this scheme is that even if there is a new employee in the company (no matter how many), the receptionist will verify and sign for the new employee after receiving the package. In fact, there are two meanings:

First, the colleagues at the entrusted front desk can sign for them, that is, the existing DOM nodes in the program have events;

Second, new employees can also be signed by the front MM, that is, the newly added DOM node in the program also has events.

Why use event delegate:

In general, the DOM needs event handlers, so we’ll just give it an event handler. What if a lot of dom needs event handlers?

Let’s say we have 100 Li’s, and each li has the same click event. Maybe we could loop through all the Li’s with a for loop, and then add events to them. What’s the impact of that?

In JavaScript, the number of event handlers added to the page is directly related to the overall performance of the page, because the need to constantly interact with dom nodes, the more times the DOM is accessed, the more times the browser will have to redraw and rearrange, which will prolong the interaction ready time of the whole page. This is why one of the main ideas of performance tuning is to reduce DOM manipulation; If you want to use the event delegate, you will put all the operations into the JS program, and the DOM operation will only need to interact once, which can greatly reduce the number of interactions with dom, improve performance;

Each function is an object, the object will use memory, object, the more the greater the memory usage rate, nature is the worse performance (not enough memory to use, is called flints, haha), such as the 100 li, would take 100 memory space, and if it was 1000, 10000, that can only say that ha ha, if use event delegation, Then we can only operate on its parent (if there is only one parent) this object, so we need a memory space is enough, is not a lot of savings, natural performance will be better.

The principle of event delegation: Event delegation is implemented using the bubbling principle of events. What is event bubbling? The event starts at the deepest node and then propagates the event up. For example, there is a node tree on the page, div>ul>li>a; For example, if we add a click event to the innermost DIV, the event will be executed layer by layer in the order of A > Li >ul>div. There is such a mechanism that if we add a click event to the outermost div, ul, Li, and A will all bubble up to the outermost div. So they all fire, and this is called event delegate, and they delegate their parent to execute the event.

This is the core of this article. Before introducing the event delegate method, let’s take a look at a general method example:

The child nodes perform the same function:

<ul id="ul1">    
    <li>111</li>    
    <li>222</li>    
    <li>333</li>    
    <li>444</li>
</ul>
Copy the code

Click li, and 123 pops up:

window.onload = function(){    
    var oUl = document.getElementById("ul1");    
    var aLi = oUl.getElementsByTagName('li');    
    for(var i=0; i<aLi.length; i++){ aLi[i].onclick =function(){            
            alert(123); }}}Copy the code

Let’s see how many dom operations are performed. First, we need to find ul, then we need to traverse Li, and then when we click Li, we need to find the location of the target Li again before we can perform the final operation.

So what if we do it in the event delegate way?

window.onload = function(){    
    var oUl = document.getElementById("ul1");   
    oUl.onclick = function(){        
        alert(123);    
}}
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.

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("ul1"); oUl.onclick =function(ev){var ev = ev || window.event;vartarget = ev.target || ev.srcElement;if(target.nodeName.toLowerCase() == 'li'{alert ()123); Alert (target. InnerHTML); }}}Copy the code

This will only trigger the event by clicking on Li, 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 imagine!

If each li is clicked differently, is it still useful to use an event delegate?

<div id="box">    
    <input type="button" id="add" value="Add" />    
    <input type="button" id="remove" value="Delete" />    
    <input type="button" id="move" value="Mobile" />    
    <input type="button" id="select" value="Choice" />
</div>
Copy the code
window.onload = function(){    
    var Add = document.getElementById("add");    
    var Remove = document.getElementById("remove");    
    var Move = document.getElementById("move");    
    var Select = document.getElementById("select");
    Add.onclick = function(){        
        alert('add');    
    };    
    Remove.onclick = function(){        
        alert('delete');    
    };    
    Move.onclick = function(){        
        alert('mobile');    
    };    
    Select.onclick = function(){        
        alert('choose');    
}}
Copy the code

I won’t go into the details of the above implementation, but it’s very simple, 4 buttons, each click to do a different operation, so it takes at least 4 DOM operations, if you use event delegate, can you optimize that?

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.nodeName.toLocaleLowerCase() == 'input') {switch(target.id){                
                case 'add' :                    
                    alert('add');                    
                    break;                
                case 'remove' :                    
                    alert('delete');                    
                    break;                
                case 'move' :                    
                    alert('mobile');                    
                    break;                
                case 'select' :                    
                    alert('choose');                    
                    break; }}}}Copy the code

With event delegates, you can do all of this in a single DOM operation, which is definitely better than the performance above

Now we’re talking about all the operations under the existing DOM node after the document is loaded, so if it’s a new node, will the new node have an event? In other words, when a new employee comes in, can he receive the delivery?

Take a look at the normal way to add nodes:

<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

Now I’m going to move li in, li turns red, I’m going to move Li out, Li turns white, and so on, and then I click the button, and I can add a li child node to ul

window.onload = function(){    
    var oBtn = document.getElementById("btn");    
    var oUl = document.getElementById("ul1");    
    var aLi = oUl.getElementsByTagName('li');    
    var num = 4;
    // The mouse turns red when it moves in and white when it moves out
    for(var i=0; i<aLi.length; i++){ aLi[i].onmouseover =function(){            
            this.style.background = 'red';        
        };        
        aLi[i].onmouseout = function(){            
            this.style.background = '#fff'; }}// Add a new node
    oBtn.onclick = function(){        
        num++;        
        var oLi = document.createElement('li');        
        oLi.innerHTML = 111*num;        
        oUl.appendChild(oLi);    
}}
Copy the code

This is a common practice, but you will find that the new LI has no event, which means that when adding child nodes, the events are not added together. This is not the desired result, so how to do? A common solution would be to wrap the for loop in a function called mHover, as follows:

window.onload = function(){    
    var oBtn = document.getElementById("btn");    
    var oUl = document.getElementById("ul1");    
    var aLi = oUl.getElementsByTagName('li');    
    var num = 4;
    function mHover () {        // The mouse turns red when it moves in and white when it moves out
    for(var i=0; i<aLi.length; i++){ aLi[i].onmouseover =function(){                
            this.style.background = 'red';            
        };            
        aLi[i].onmouseout = function(){                
            this.style.background = '#fff';            
        }        
    }}    
    mHover ();    // Add a new node
    oBtn.onclick = function(){        
        num++;        
        var oLi = document.createElement('li');        
        oLi.innerHTML = 111*num;        
        oUl.appendChild(oLi);        
        mHover ();    
}}
Copy the code

Although the function is implemented, it looks good, but in fact, there is no doubt that another DOM operation is added, which is not desirable in terms of optimizing performance. So can the way with event delegation achieve optimization?

window.onload = function(){    
    var oBtn = document.getElementById("btn");    
    var oUl = document.getElementById("ul1");    
    var aLi = oUl.getElementsByTagName('li');    
    var num = 4;
    // Event delegate, the added child element also has events
    oUl.onmouseover = function(ev){        
        var ev = ev || window.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"; }};// Add a new node
    oBtn.onclick = function(){        
        num++;        
        var oLi = document.createElement('li');        
        oLi.innerHTML = 111*num;        
        oUl.appendChild(oLi);    
}}
Copy the code

See, the above is the way to entrust with events, the newly added effect of child elements with the event, we can find that when using event delegation, don’t need to traverse the element’s child nodes, only need to add events to the parent element, the others are all in js, so can greatly reduce the dom manipulation, This is the essence of event delegation.

Summary: What kind of events can and cannot be used for event delegation?

Suitable events for event delegation: click, mouseDown, mouseup, keyDown, keyUp, keyPress.

It is worth noting that mouseover and Mouseout do have event bubbles, but they require special care because they are not easy to handle because they require constant calculations of their positions.

Mousemove, for example, has to calculate its position every time, which is very difficult to control. For example, focus, blur, etc., it does not have the bubbling feature, so it cannot use event delegate naturally.