I. Event flow
Event flow: The order in which events are received from the page.
<html>
<body>
<div>HELLO WORLD</div>
</body>
</html>
Copy the code
Event bubbling: Proposed by Microsoft, events are received by the most specific element and propagated up the hierarchy to less specific nodes (Document objects). Div ->body-> HTML ->document->window
Event capture: Developed by Netscape, events are received by less specific nodes (document objects) and propagated down the hierarchy to the most specific nodes. The above code events flow: window(browser implementation includes this node) ->document-> HTML ->body>div.
DOM event flow mechanism (event propagation) : Event flow includes event capture, being targeted, and event bubbling phases.
Event capture: window->document-> HTML ->body
At the target: div
Event bubble: div->body-> HTML ->document->window
This article simply write a clear (refer to below article marked as 1) link: segmentfault.com/a/119000000…
Event handlers and this Pointers
Event handler: Also called event handler or event listener, a function that responds to an event. The event handler begins with “on” and the event handler that responds to click is onclick.
Method 1: HTML event handlers
Specified using an HTML feature with the same name as the event handler.
Event handlers are dynamically created functions. This refers to the target element of the event, and the callback extends the scope to directly access the properties of the event target function.
The scope chain of the callback function execution environment: variable object containing all the attributes of the event target element -> variable object containing all the attributes of document -> callback function variable object -> global variable object, as shown below. Therefore, the attribute values of the event target element are used directly in the callback function.
function(){ with(document){ with(this){ console.log(value); // Element attribute values}}}Copy the code
Event handlers are globally-scoped functions. This refers to the Window object. To get the event target object, use event.target. (It can be considered that this function is no longer called by the event target object when the callback is called.)
<body> <! <input type="button" id="ele" value=" ele" onclick="console.log('ele',value,this)"></input> <! <input type="button" id="ele0" value=" ele0" onclick="handleClick(event)"></input> <script> Function handleClick(event){console.log("ele0 ",this) // Outputs the window object console.log("ele0 ") ",event.target.value,event.target); } </script> </body>Copy the code
Event handlers bound in this manner handle events during the event bubble phase. To modify the HTML code for link 1, click on the light blue section in the center of the page to pop up 123, then 456, and finally 789.
<div id="wrap" onclick="alert('789')">
<div id="outer" onclick="alert('456')">
<div id="inner" onclick="alert('123')"></div>
</div>
</div>
Copy the code
Method 2: DOM0 event handler
Assign the callback function to the event handler property of the element. Event handlers handle events in the event bubbling phase. Based on the HTML and CSS of link 1, modify the JS as follows. When you click on the light blue section in the center of the page, 123 pops up, then 456, and finally 789.
var wrap = document.getElementById('wrap');
var outer = document.getElementById('outer');
var inner = document.getElementById('inner');
wrap.onclick=function(){
alert('789');
};
outer.onclick=function(){
alert('456');
};
inner.onclick=function(){
alert('123');
};
Copy the code
Method 3: DOM2-level event handler
The addEventListener function takes the event name, the event handling callback, and the event capture mode representation (true for capture, false for bubble (default)). Events can be handled in the bubble phase or capture phase, depending on Settings.
As shown below, neither method 2 nor method 3 bound event handlers can use arrow functions, otherwise this points to something other than the event target. (Arrow function does not have this, this of the global execution environment scope is found along the scope chain)
<body> <div> <input type="button" id="ele1" value=" click ele1"></input> <input type="button" id="ele2" </input> <input type="button" id=" button" </input> <input type="button" id=" button" Var ele1= document.getelementById ("ele1") ele1.onclick=function(){value=" click ele4"></input> </div> <script> var ele1= document.getelementById ("ele1") ele1.onclick=function(){ console.log("ele1 ",this); Var ele2= document.getelementById ("ele2") ele2.onclick=()=>{console.log("ele2 ",this); Var ele3= document.getelementById ("ele3") ele3. AddEventListener ("click",function(){ console.log("ele3 ",this); Var ele4= document.getelementById ("ele4") ele4.addeventListener ("click",()=>{console.log("ele4 ") ",this); },false) </script> </body>Copy the code
The advantages and disadvantages of the above and which method should be used:
MDN Official document: developer.mozilla.org/zh-CN/docs/…
HTML event handlers: Not recommended because HTML and JavaScript are too coupled. The other two can be used at will.
DOM0 level event handler: good compatibility, downward compatibility to IE8, listener can be removed. However, assigning the onclick attribute to the event target object multiple times overrides the previous attribute value, and you cannot bind multiple event handlers that listen for the same event.
Dom2-level event handlers: only backward compatible with IE9, listeners can be removed, and the event target object can be bound to multiple event handlers that listen for the same event, triggering in the order of addition.
Mode 4 :IE event handler
This method is only supported by Internet Explorer. If the page entry needs to support Internet Explorer 8 or lower versions for compatibility, this method is required. Add
to the header of the document and run it in Internet Explorer. This points to the window object. An event target object can be bound to multiple event handlers that listen for the same event, firing in the reverse order of addition.
<body> <div> <input type="button" id="ele" value=" ele"></input> </div> <script> var ele= document.getelementbyid ("ele") ele.attachEvent("onclick",function(){ console.log("ele",this); // Output window object}) </script> </body>Copy the code
Cross-browser event handlers
Combined with the above event handler, compatible with various browsers and IE lower versions of the code:
Remove the event handler
Why do best practices remove practice handlers? This is because the reference called back by the event listener can cause memory leaks, and in older versions of IE there can be memory leaks caused by circular references, and even the event listener itself can be leaked (juejin.cn/post/699800…). . Also, event handlers are inherently memory hogs and are best removed to make room if they are not needed. On the other hand, assigning an event handler to an element creates one more link between the running browser code and the JavaScript code that supports page interaction, and the more links, the slower the page executes.
Removal time:
1. Make sure event handlers are removed if necessary
<div id="myDiv"> <input type="button" value="Click me" id="myBtn"/> </div> <script> var btn=document.getElementById("myBtn"); btn.onclick=function(){ console.log("clicked") btn.onclick=null; // Remove event handler before BTN element is overwritten document.getelementById ("myDiv").innerhtml ="Processing..." ; } </script>Copy the code
2. Remove it when the page is uninstalled
Removal method:
- Dom0-level event handler: btn.onclick=null
- Dom2-level event handler: the btn.removeEventListener() function
- IE event handler: btn.detachevent () function
3. Event object
No matter how the event handler is bound, the browser passes the event object into the event handler. An event object exists during the execution of an event handler and is destroyed upon completion. The IE event handler is special (added by attachEvent), event objects are not passed as arguments to the event handler, but are accessed through window.event.
1. Event. currentTaget and event.target
Based on the HTML and CSS of link 1, modify the JS as follows by clicking on the light blue part in the center of the page (inner element)
var wrap = document.getElementById('wrap');
var outer = document.getElementById('outer');
var inner = document.getElementById('inner');
wrap.onclick=function(event){
console.log('789',event.target,event.currentTarget);
};
outer.onclick=function(event){
console.log('456',event.target,event.currentTarget);
};
inner.onclick=function(event){
console.log('123',event.target,event.currentTarget);
};
Copy the code
The output is 123, inner element, inner element; 456, inner element, outer element; 789, inner element, wrap element;
Target: The target element of the event;
CurrentTarget: the element whose event handler is currently processing the event; In IE event objects, event.srcElement represents the event target object.
In the example above, inner is the element being clicked, which is the target element of the event. The outer elements of inner, outer and wrap, are also bound to onclick event handlers, so click events are also handled. As the event bubbles, the element currently handling the click event changes, so currentTarget changes and Target is always the target element of the event being clicked.
Event.preventdefault () : preventDefault behavior for specific events
It’s used for links. If you want to prevent this from happening, call the event.preventDefault() method in the event handler for the clicked event.
In IE event objects, event.returnValue=false prevents the default behavior of a particular event.
Event.stoppropagation () : Cancel the event to further capture or bubble. If this function is called in the event handler of the inner element, the event is not propagated to the outer element.
var wrap = document.getElementById('wrap');
var outer = document.getElementById('outer');
var inner = document.getElementById('inner');
wrap.onclick=function(event){
console.log('789');
};
outer.onclick=function(event){
console.log('456');
};
inner.onclick=function(event){
console.log('123');
event.stopPropagation();
};
Copy the code
In the above code, the inner element is clicked, but the event.stopPropagation() function is called in the inner element’s event handler, so the command prints 123.
In IE event objects, event.cancelBubble=true cancels the event to further capture or bubble.
4. Event delegation
Event delegate: A solution to the problem of too many event handlers using the event bubble mechanism.
The element that responds to an event is not the same as the element that binds to the event. Generally, the element that binds to the event is the parent of the element that responds to the event. This requires determining how to find the element to respond to the event based on what the page deconstructs and does in response to the event, which is critical.
Reference link: juejin.cn/post/684490… The following example is rewritten from a reference link.
<ul id="list"> <li><span>item 1</span></li> <li>< li>item 2</li> <li>item 3</li> </ul> <script> /* The li element responds to an event and prints the contents of the Li element when the event is triggered. The event delegation mechanism can be used to bind events to UL, the parent element of LI. But if there are elements inside the Li element, the event delegate is not so easy to write. Because event.target is different from the element to bind to. * / document. GetElementById (' list '). The addEventListener (' click ', function (e) {/ / compatibility with var event = e | | window. The event; var ele = event.target || event.srcElement; // The response event element is expected to be li while(! ele.matches("li")){ ele=ele.parentNode; If (ele. Matches ("li")) {console.log(' The content is: ',ele. InnerHTML); }}); </script>Copy the code
The biggest advantage of event delegation is that it reduces the memory consumption of defining event listeners and speeds up the page by allowing the running browser code to make fewer links to the JavaScript code that supports page interaction.