During the front-end development process, we often encounter the problem of adding events to page elements. There are also many JS methods to add events, including directly added to the page structure, and some JS event monitoring methods. Since each browser has different mechanisms for event bubble event monitoring, the le browser only has event bubbles and no event monitoring mechanism, and the compatibility issue of event listening is the biggest problem:
1. Write the event method directly on the page structure
function eventfun(){ //console.log(this); } <input type="button" onclick="eventfun()" value="button" />//This involves a problem of this scope. Eventfun is also a global function here. The object is [object Window], and this points to window.To solve this scope problem, you can use the method of adding event variables to the global function, and pass this object as a parameter to the function inside the page structure
<input type="button" onclick="eventfun2(this)" value="button2" /> function eventfun2(eve){//Here the event object is passed as a parameter to the global method eve.name="alex"; window.name="robin"; console.log(this);//[object Window] console.log(eve);// [object HTMLInputElement] console.log(this.name);// robin console.log(eve.name);// alexvar self=eve; console.log(this.name);// robin console.log(self.name);//alex alert(window.name); alert(self.name); }2. Using the method of assigning value to event attributes is a method of binding to events, but the limitation of this method is that it can only bind one method to events. If multiple bindings are bound, one method will prevail.
HTMLElementobject.onclick = fucntion(){//Use this method to assign value to event attributes, this pointer will point to the window object, not the event object, so this method is a reference
//js code fun1(); fun2(); fun3(); console.log(this);//window.object } function dosomething(){ //js code } HTMLElementobject.onclick = dosomething;//Use this form of assigning value to event object attributes, this pointer points to the event execution object console.log(this);//htmlElementObject3. Event propagation - bubble and capture
The DOM event standard defines two event streams, which are significantly different and may have a considerable impact on your application. These two event streams are capture and bubble. Like many web technologies, Netscape and Microsoft implemented them differently before they became standard. Netscape chose to implement capture event streams, while Microsoft implemented bubble event streams. Fortunately, W3C decided to use both methods in combination, and most new browsers follow these two event streaming methods.
By default, events use bubble event streams, and no capture event streams are used. However, in Firefox and Safari, you can explicitly specify the use of capture event streams by passing in the useCapture parameter when registering the event and setting this parameter to true.
Bubble event stream
When an event is triggered on a DOM element, for example, the user clicks the mouse on the client name node, the event will follow the various parent nodes inherited from which the node bubbles through the entire DOM node hierarchy until it encounters a node that is attached to the event type processor. At this time, the event is the onclick event. The bubbling of events can be terminated at any time during the bubbling process. In browsers that comply with W3C standards, you can call the stopPropagation() method on the event object, and in Internet Explorer, you can set the cancelBubble attribute of the event object to true. If the event is not stopped, the event will bubble through the DOM until it reaches the document root.
Capture event flow
The processing of the event starts at the root of the DOM level, rather than from the target element that triggers the event, and the event is passed down in sequence from all the ancestor elements of the target element. In this process, events are captured by various inherited derived elements from the document root to the event target element. If the event listener sets the useCapture attribute to true when registered, they can be assigned to any element during this period to handle the event; otherwise, events will be subsequently passed to the next element on the derived element path until the target element. After the event reaches the target element, it will then bubble through the DOM node.
Modern event binding method
For the previous lesson, using traditional event binding has many drawbacks, such as the inability to register multiple event handlers on the same event of an object. And browsers and W3C are not without considering this, so in modern browsers, they have their own methods to bind events.
W3C DOM
obj.addEventListener(evtype,fn,useCapture) - W3C provides method to add event handling functions. obj is the object to add events, evtype is the event type, without on prefix, fn is the event handler function, if useCapture is true, the event handler function is executed in the capture stage, otherwise it is executed in the bubble stage
obj.removeEventListener(evtype,fn,useCapture)--W3C provides method for deleting event handling functions
Microsoft IE method
obj.attachEvent(evtype,fn) - The method provided by IE to add event handling functions. obj is the object to add events, evtype is the event type, with on prefix, fn is the event handler function, IE does not support event capture
obj.detachEvent(evtype,fn,) - IE provides a method to delete event handling function, evtype contains on prefix
A way to integrate both
function addEvent(obj,evtype,fn,useCapture) { if (obj.addEventListener) { obj.addEventListener(evtype,fn,useCapture); } else { obj.attachEvent("on"+evtype,fn);//IE does not support event capture} else { obj["on"+evtype]=fn;//In fact, this situation will not exist} } function delEvent(obj,evtype,fn,useCapture) { if (obj.removeEventListener) { obj.removeEventListener(evtype,fn,useCapture); } else { obj.detachEvent("on"+evtype,fn); } else { obj["on"+evtype]=null; } }There is a problem with the IE attach method, which is that when using attachEvent, this points to window, not obj! Of course, there is a solution for this!
But there is another problem with IE's attachmentEvent method. The same function can be registered with the same object and the same event multiple times. Solution: Abandon IE's attachmentEvent method! The attachEvent method under IE does not support capture, which is not much different from traditional event registration (except for binding multiple event handlers), and the attachmentEvent method of IE has a memory leak problem!
addEvent, delEvent modern version
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>js event listening</title> <style> table td{font:12px; border-bottom:1px solid #efefefef;} </style> </head> <body> <div id="outEle" style="padding:10px; border:1px solid #b2b2b2; background:#efefefefef;"> <input type="button" onclick="eventfun()" id="button" value="button" /><br /> <input type="button" onclick="eventfun2(this);" id="button2" value="button2" /><br /> <input type="button" id="button3" value="button3" /><br /> <input type="button" id="button4" value="button4" /><br /> <table id="htmlEleTable" style="border:1px solid #b2b2b2; background:#fff;"> <tr id="1111"><td>111111111111111111111111111111</td></tr> <tr id="22222"><td>222222222222222222222222222222</td></tr> <tr id="33333333333333333333333333333333333</td></tr> <tr id="44444"><td>4444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444</td></tr> <tr id="555555555555555555555555555</td></tr> </table> </div> <script language="javascript" type="text/javascript"> function eventfun(){//1. Directly write the js method on the page structure console.log(this);//This involves a problem with this scope. Eventfun is a global function, the object is window, and this points to window alert(this); } function eventfun2(eve){// Here pass the event object as a parameter to the global method eve.name="alex";// window.name="robin"; console.log(this);//[object Window] console.log(eve);// [object HTMLInputElement] console.log(this.name);// robin console.log(eve.name);// alex var self=eve; console.log(this.name);//robin console.log(self.name);//alex alert(window.name); alert(self.name); } function eventfun3(){//1. Directly write the js method on the page structure console.log(this);//This involves a problem of this scope. eventfun is a global function, the object is window, and this points to window console.log(this.id); alert(this); alert(this); alert(this.id); //var outEleObj = EventUtil.$("outEle"); //removeEvent(outEleObj,"click",eventfun3); } /* var EventUtil = {}; EventUtil.$ = function(id){ return document.getElementById(id); } EventUtil.openmes = eventfun3; EventUtil.addEventHandle = function(eventTarget,eventtype,eventHandle){//Define the object element, event type for event listening, event function if(eventTarget.attachEvent){ eventTarget.attachEvent("on"+eventtype,eventHandle); }else if(eventTarget.addEventListener){ eventTarget.addEventListener(eventtype,eventHandle,false) }else{ eventTarget["on" + eventtype] = null; } }; EventUtil.deleEventHandle = function(eventTarget,eventtype,eventHandle){//Define the object element, event type for event listening, event function if(eventTarget.detachEvent){ alert("on"+eventtype); alert("on"+eventHandle); eventTarget.detachEvent("on"+eventtype,eventHandle); }else if(eventTarget.removeEventListener){ eventTarget.removeEventListener(eventtype,eventHandle,false) }else{ eventTarget["on" + eventtype] = null; } };*/ var EventUtil={ $:function(id){ return document.getElementById(id); }, but4fun:function(){ console.log(this); this.addEventHandle(); }, eventfun3:function(){ console.log(this); alert(this); delEvent(obj,evtype,fn,useCapture); } } /***Use addEventListener,attachEvent for listening function addEvent(obj,evtype,fn,useCapture){ if (obj.addEventListener) { obj.addEventListener(evtype,fn,useCapture); }else if(obj.attachEvent){ obj.attachEvent("on"+evtype,function () { fn.call(obj); }); }else { obj["on"+evtype]=fn;//In fact, this situation will not exist} } function delEvent(obj,evtype,fn,useCapture) { if (obj.removeEventListener) { obj.removeEventListener(evtype,fn,useCapture); } else if(obj.detachEvent){ obj.detachEvent("on"+evtype,fn); } else { obj["on"+evtype]=null; } } function addEvent(obj,evtype,fn,useCapture) { if (obj.addEventListener) {//Priority is given to the W3C event registration scheme obj.addEventListener(evtype,fn,!!useCapture); } else {//When addEventListener is not supported (IE), since IE does not support capture at the same time, it is better to use traditional event binding if (!fn.__EventID) {fn.__EventID = addEvent.__EventHandlesCounter++;} // Assign a unique ID to each event handler if (!obj.__EventHandles) {obj.__EventHandles={};} //_EventHandles attribute is used to save references to all event handlers//Classified by event type if (!obj.__EventHandles[evtype]) {//On the first time an event is registered obj.__EventHandles[evtype]={}; if (obj["on"+evtype]) {//The event handling function has been registered in the traditional way before (obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;//Add to the reserved 0 bits// and add an ID to the original event handling function } obj["on"+evtype]=addEvent.execEventHandles; //When an event occurs, execEventHandles traverse the table obj.__EventHandles[evtype] and execute the function in it} } } } addEvent.__EventHandlesCounter=1;//Counter, 0 bit reserved it with addEvent.execEventHandles = function (evt) {//Tranquility through all event handlers and execute if (!this.__EventHandles) {return true;} evt = evt || window.event; var fns = this.__EventHandles[evt.type]; for (var i in fns) { fns[i].call(this); } }; /* function delEvent(obj,evtype,fn,useCapture) { if (obj.removeEventListener) {//First use W3C method to remove the event handler function obj.removeEventListener(evtype,fn,!!useCapture); } else { if (obj.__EventHandles) { var fns = obj.__EventHandles[evtype]; if (fns) { delete fns[fn.__EventID];} } } } } function fixEvent(evt) {//The fixEvent function is not executed separately. It must have an event object parameter, and it will be executed only when the event occurs! The best way is to integrate it into the execEventHandles of the addEvent function if (!evt.target) { evt.target = evt.srcElement; evt.preventDefault = fixEvent.preventDefault; evt.stopPropagation = fixEvent.stopPropagation; if (evt.type == "mouseover") { evt.relatedTarget = evt.fromElement; } else if (evt.type =="mouseout") { evt.relatedTarget = evt.toElement; } evt.charCode = (evt.type=="keypress")?evt.keyCode:0; evt.eventPhase = 2;//IE only works in the bubble stage evt.timeStamp = (new Date()).getTime();//Set it only to the current time} return evt; } fixEvent.preventDefault =function () { this.returnValue = false;//This here points to a certain event object, not fixEvent }; fixEvent.stopPropagation =function () { this.cancelBubble = true; };*/ //console.log(EventUtil.$("button3"));//Return the object attribute of the EventUtil function //EventUtil.$("button3").onclick= eventfun;//2. Use the method of assigning values to the object event attribute to realize the listening of events //EventUtil.$("button3").onclick= eventfun2;// When adding multiple methods to the event attribute, the latter is //EventUtil.$("button3").onclick= eventfun;//Event capture is from the parent inspection of the event object layer by layer to the window object var EventUtil =function(){ function getByid(id){ return document.getElementById(id); }; // written by Dean Edwards, 2005 // with input from Tino Zijdel, Matthias Miller, Diego Perini // http://dean.edwards.name/weblog/2005/10/add-event/ function addEvent(element, type, handler) { if (element.addEventListener) { element.addEventListener(type, handler, false); } else { // assign each event handler a unique ID if (!handler.$$guid) handler.$$guid = addEvent.guid++; // create a hash table of event types for the element if (!element.events) element.events = {}; // create a hash table of event handlers for each element/event pair var handlers = element.events[type]; if (!handlers) { handlers = element.events[type] = {}; // store the existing event handler (if there is one) if (element["on" + type]) { handlers[0] = element["on" + type]; } } // store the event handler in the hash table handlers[handler.$$guid] = handler; // assign a global event handler to do all the work element["on" + type] = handleEvent; } }; // a counter used to create unique IDs addEvent.guid = 1; function removeEvent(element, type, handler) { if (element.removeEventListener) { element.removeEventListener(type, handler, false); } else { // delete the event handler from the hash table if (element.events && element.events[type]) { delete element.events[type][handler.$$guid]; } } }; function handleEvent(event) { var returnValue = true; // grab the event object (IE uses a global event object) event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); // get a reference to the hash table of event handlers var handlers = this.events[event.type]; // execute each event handler for (var i in handlers) { this.$$handleEvent = handlers[i]; if (this.$$handleEvent(event) === false) { returnValue = false; } } return returnValue; }; function fixEvent(event) { // add W3C standard event methods event.preventDefault = fixEvent.preventDefault; event.stopPropagation = fixEvent.stopPropagation; return event; }; fixEvent.preventDefault = function() { this.returnValue = false; }; fixEvent.stopPropagation = function() { this.cancelBubble = true; }; function tableAddEvent(){ }; return{ add:addEvent, remove:removeEvent, $:getByid } }(); var outEleObj = EventUtil.$("outEle"); //addEvent.apply(EventUtil,[outEleObj,"click", eventfun3]); //EventUtil.add(outEleObj,"click",eventfun3); var inputObj = EventUtil.$("button4"); var tableEle = EventUtil.$("htmlEleTable"); var tabTrEle = tableEle.getElementsByTagName("tr"); EventUtil.add(tableEle,"click",eventfun3); for (i=0; i<tabTrEle.length; i++){ EventUtil.add(tabTrEle[i],"click",eventfun3); } EventUtil.remove(tableEle,"click",eventfun3);//Event deletion method EventUtil.add(tableEle,"click",eventfun3);//EventUtil.add(inputObj,"click",eventfun3); //EventUtil.remove(outEleObj,"click",eventfun3); //Console.log(addEvent); //addEvent(inputObj,"click",eventfun3,true); //delEvent(outEleObj,"click",eventfun3,false); </script> </body> </html>PS: Here we provide you with an online tool about JS events, which summarizes the commonly used event types and function functions of JS:
A complete list of javascript events and functions:
http://tools.VeVB.COM/table/javascript_event