Home >Web Front-end >JS Tutorial >Detailed explanation of event delegation in javascript
I saw an interview question these days. It asked you to add a click event to 1,000 li's. How should you add it? Most people's first impression may be that just add a click event to each li. Then If this is the case, it is estimated that you will be GG during the interview. Here we have withdrawn our event bubbling and capturing mechanism, as well as the event delegation mechanism. Let’s take a look at the above.
First, let’s talk about event bubbling. As for the event capture mechanism, event bubbling was proposed by Microsoft, and event capture was proposed by Netscape. At that time, the two companies were at loggerheads. Later, W3C had no choice but to adopt a compromise approach. After the event is generated, it is first captured and then bubbled,
Usually, there are three methods of listening to events in js, namely:
ele.addEventListener(type, listener, [useCapture]); //IE6~8 does not support
ele.attachEvent('on'+type,listener);//Supported by IE6~10, not supported by IE11
ele.onClick=function(){};//Supported by all browsers
Defined in the w3c specification The three event stages are the capture stage, the target stage, and the bubbling stage. In the dom2 level regulations specified by w3c, addEventListener is used to listen for events. So we will explain it with addEventListener. First, fake bubbling is just like you Just like throwing a stone into the water, the bubbles in the water will pop up from below, which means that the trigger event will be triggered from the direction of the child element to the parent element, while the capture mechanism is exactly the opposite. The capture mechanism is to trigger the event from the parent element to the child element. Trigger, and the third parameter in the addEventListener function is used to decide whether to use the capture mechanism or the bubbling mechanism. When useCapture is true, it is the capture mechanism. When useCapture is false, it is the bubbling mechanism. Let’s take a look at the example:
Copy code
<div class="parent"> <div class="child"> </div> </div> <script> var parent = document.getElementsByClassName('parent')[0]; var child = document.getElementsByClassName('child')[0]; parent.addEventListener('click',function(){ console.log("这里是父元素"); },false); child.addEventListener('click',function(){ console.log("这里是子元素"); },false); </script>
When we click on the child element, the picture above is displayed. When we change false to true, we will find that the execution order will be reversed. This is the difference between event bubbling and capturing. They are just right. On the contrary,
The disadvantage of using this binding mechanism is that it will be a particularly troublesome thing to bind events to each object. It will be especially troublesome when we want to delete an event or change an event. It's cumbersome, and more importantly, we have increased the association between JavaScript and DOM nodes, and if there is a circular reference, it is likely to cause memory leaks. These are its drawbacks,
Then one way to solve this drawback The method is event delegation. This method allows you to avoid adding events to each node one by one. What it does is bind these listening events to the parent elements of these nodes. On the parent element This listening function automatically determines which child element triggered the event, so that it can operate on the child element that triggered the event. The example we give here is an example given by davidwalsh:
Now we have a parent element ul And several li sub-elements,
<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> </ul>What we want to achieve now is that when we click on each li node, the contents of the li node will be output. According to the above writing, you can select these li and add them later. Use these methods, and then remove them when they are no longer needed. If there are 100 li or 1000 li, this will become your nightmare. A better solution is to add a listening event to the parent element, and then The question is how to determine which li was clicked? We can judge the target of the current event in the listening event to determine whether it is the node we are looking for. Here we have a simple example:
// 找到父元素,绑定一个监听事件 document.getElementById("parent-list").addEventListener("click", function(e) { // e.target是点击的元素 // 如果它是li元素 if(e.target && e.target.nodeName == "LI") { // console.log("List item ", e.target.id.replace("post-", ""), " was clicked!"); } });
When in ul After a click event occurs, because addEventListener is a bubbling event by default, the listening event will be executed when the underlying event bubbles up. After the event is triggered, we will detect whether it is the target element we are looking for. If not, it will be ignored. , then we can not only check whether the tag of the target element is the target element we need, we can also detect it based on the attributes or class names of the target element, and use the ele.maeches API to process,
document.getElementById("myDiv").addEventListener("click",function(e) { // e.target 就是当前被点击的元素 if (e.target && e.target.matches("a.classA")) { console.log("Anchor element clicked!"); } });
So we can It can be seen that using event proxy can bring us a lot of convenience and avoid many pitfalls. Using event proxy is a very powerful method.