JS event delegation (event proxy) detailed

JS event delegation (event proxy) detailed

Event delegation is a classic question type for front-end interviews. It is helpful whether it is for future interviews or for development!

In fact, I am not very clear about this concept, so I wrote this blog,
one is to prevent myself from forgetting it in the future, and the
other is to give reference to those friends like me.

So what is event delegation?

It also has a name called event proxy. In terms of JavaScript advanced programming, event delegation is to use event bubbling, and only specify an event handler to manage all events of a certain type.

It's so official, so let's take a look at the chestnut that the great online gods all use, which is to take express delivery to explain this phenomenon.

有三个同事预计会在周一收到快递。
为签收快递,有两种办法:
一是三个人在公司门口等快递;
二是委托给前台MM代为签收。
现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。
前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。
这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

There are actually two meanings here;

First, the colleague who entrusts the front desk can sign for it, that is, the existing domnodes in the program have events;

Second, new employees can also be signed for by the front desk MM, that is, the newly added domnodes in the program also have events.

Why use event delegation:

  1. Improve performance and efficiency

  2. Reduce event registration and save memory usage

  3. Future elements do not need to register for events again

  4. Elements added later will also have events

The principle of event delegation:

Event delegation is realized by using the bubbling principle of events.

What is event bubbling?

DOM event flow in JS (event bubbling, event capture)

for example:

页面上有这么一个节点树,div>ul>li>a
比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,
那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,
这就是事件委托,委托它们父级代为执行事件。

How to implement event delegation:

Finally arrived at the core part of this article, haha, before introducing the method of event delegation, let's look at an example of a general method:

The child nodes achieve the same function:

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

The realization function is to click liand pop up 123:

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);
        }
    }
}

The meaning of the above code is very simple. I believe many people have realized it like this. Let’s see how many domoperations there are . First, find ul, then traverse li, and then liwhen you click , find lithe location of the target again to execute the final The operation, every time you click, you will find it once li;

So what if we use event delegation?

window.onload = function(){
    
    
    var oUl = document.getElementById("ul1");
   oUl.onclick = function(){
    
    
        alert(123);
    }
}

Here the parent is used ulfor event processing. When liclicked, due to the bubbling principle, the event will bubble ulup. Because there ulis a click event, the event will be triggered. Of course, here when clicked ul, it will also be triggered. , Then the problem is here, what if I want the effect of the event proxy to be the same as the effect of the event directly to the node, for example, only a click liwill trigger, not afraid, we have a trick:

EventThe event object provides a property called target, which can return the target node of the event. We call it the event source, which means that targetit can be expressed as the current event operation dom, but not the actual operation dom. Of course, this is compatible. Standard browsing used ev.target, IE browser with event.srcElement, then just get the position of the current node does not know what the name of the node, where we use nodeNameto get specifically what label name, this is a return of capital, we need to do to lower case Comparison (a problem of habit):

window.onload = function(){
    
    
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    
    
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    if(target.nodeName.toLowerCase() == 'li'){
    
    
         alert(123);
         alert(target.innerHTML);
    }
  }
}

In this way, only the click liwill trigger the event, and only one domoperation will be performed at a time . If there are a lilarge number domof operations, the operation will be greatly reduced , and the optimized performance can be imagined!

The above example means that the lioperation is the same. If the effect of each liclick is different, is it still useful to use event delegation?

<div id="box">
        <input type="button" id="add" value="添加" />
        <input type="button" id="remove" value="删除" />
        <input type="button" id="move" value="移动" />
        <input type="button" id="select" value="选择" />
    </div>
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('添加');
            };
            Remove.onclick = function(){
                alert('删除');
            };
            Move.onclick = function(){
                alert('移动');
            };
            Select.onclick = function(){
                alert('选择');
            }
            
        }

I won’t say much about the effects achieved above. It’s very simple dom. If you click on each of the 4 buttons to do different operations, you need at least 4 operations. If you use event delegation, can you optimize it?

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('添加');
                            break;
                        case 'remove' :
                            alert('删除');
                            break;
                        case 'move' :
                            alert('移动');
                            break;
                        case 'select' :
                            alert('选择');
                            break;
                    }
                }
            }
            
        }

With event delegation, you domcan complete all the effects with only one operation, which is definitely better than the above performance

Now we are talking about operations under documentexisting domnodes that have been loaded , so if it is a new node, will there be events for the new node? In other words, a new employee comes, can he receive the courier?

Take a look at the normal method of adding nodes:

<input type="button" name="" id="btn" value="添加" />
    <ul id="ul1">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
    </ul>

Now it is moving in li, liturning red, moving out li, liturning white, such an effect, and then click the button to uladd a lichild node to it

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);
            };
        }

This is a general practice, but you will find that lithere is no event for the new addition , which means that when adding a child node, the event is not added together. This is not the result we want, so what should we do? The general solution will be this, forwrap the loop with a function, named as mHoverfollows:

window.onload = function(){
    
    
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            function mHover () {
    
    
                //鼠标移入变红,移出变白
                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 ();
            //添加新节点
            oBtn.onclick = function(){
    
    
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
                mHover ();
            };
        }

Although the function is realized, it looks good, but in fact there is undoubtedly another domoperation added, which is not advisable in terms of optimizing performance. Then there is an event delegation method, can it be optimized?

window.onload = function(){
    
    
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            //事件委托,添加的子元素也有事件
            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";
                }
                
            };
            
            //添加新节点
            oBtn.onclick = function(){
    
    
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
            };
        }

Look, the above is the way of event delegation, the newly added child elements have event effects, we can find that when using event delegation, there is no need to traverse the child nodes of the element, only the parent element Just add an event, and everything else is jsexecuted inside, which can greatly reduce domoperations. This is the essence of event delegation.

to sum up:

So what kind of events can be used for event delegation, and what kinds of events can't be used?

Suitable entrusted with events clickevents: mousedown, mouseup, keydown, keyup, keypress, .

It is noteworthy, mouseoverand mouseoutalthough there are event bubbling, but when dealing with them need special attention, as it is often calculate their position, not easy to deal with.

There are many unsuitable ones. For example, mousemoveevery time you have to calculate its position, it is very difficult to control. For example focus, blurthere is no bubbling feature in itself, so naturally you cannot use events. Commissioned.

Alright! Let’s stop here today! If you have any questions, please comment below! I will try my best to answer your questions!
Insert picture description here

Guess you like

Origin blog.csdn.net/XVJINHUA954/article/details/111894759