Javascript event binding learning points and javascript event binding
Event binding can be divided into two types: traditional event binding (Inline model, script model) and modern event binding (DOM2 model ). Modern event binding provides greater and more convenient functions in traditional binding.
A traditional event binding Problem
Inline models in traditional event binding are rarely discussed. Let's take a look at the script model. The script model assigns a function to an event processing function. Traditional bindings such:
window.onload=function(){ var box=document.getElementById('box'); box.onclick = function(){ alert('Lee'); };};
Problem 1: one event processing function triggers two events
If a page has two or more JavaScript codes, and the first JavaScript code is developed by the first program, the second JavaScript code is developed by the second programmer. The first window. onload is overwritten, as shown in figure
window.onload=function(){ alert('Lee');};window.onload=function(){ alert('Mr.lee');}
Only Mr. lee is printed.
There is actually a way to solve this problem. Let's look at the two forms below.
A:
Alert (window. onload); // The window is not registered at the beginning. onload, Which is nullwindow. onload = function () {alert ('Lee ') ;}; alert (window. onload); // If window already exists. onload: prints the functionwindow function. onload = function () {alert ('Mr. lee ');}
B:
Alert (typeof window. onload); // No window at the beginning. the old version of Firefox displays undefined. The new version displays object and window. onload = function () {alert ('Lee ') ;}; alert (typeof window. onload); // If window already exists. onload, all browsers will display functionwindow. onload = function () {alert ('Mr. lee ');}
So there is a solution.
Window. onload = function () {alert ('lil') ;}; if (typeof window. onload = 'function') {var saved = null; // save the last event object saved = window. onload;} // saved is the window. onload, saved () is equivalent to window. onload (), but window. onload () cannot be executed // so saved () is equivalent to window. onload = function () {} window. onload = function () {if (saved) {saved (); // execute the previous event window. onload = function () {}} alert ('Mr. lee '); // execute this event}
Question 2: Event switcher
Switch a div with the id of box so that the background red and blue are switched directly:
Window. onload = function () {var box = document. getElementById ('box'); box. className = "red"; box. onclick = function () {alert ('lil'); // only blue is executed once. call (this); // call a function through an anonymous function. this indicates the window, so you can pass it through call.} function blue () {this. className = "blue"; this. onclick = red;} function red () {this. className = "red"; this. onclick = blue ;}
Although the above Code implements the switchover function, the dialog box is executed only once.
// Add the event function // obj equivalent to window // type equivalent to onload // fn equivalent to function () {} function addEvent (obj, type, fn) {// used to save the previous event var saved = null; if (typeof obj ['on' + type] = 'function ') {saved = obj ['on' + type]; // Save the previous event} obj ['on' + type] = function () {if (saved) {saved ();} fn. call (this) ;}} addEvent (window, 'load', function () {var box = document. getElementById ("box"); // addEvent (box, 'click', function () {// this is achieved, and is executed every time, not overwritten // alert ('ss'); //}); addEvent (box, 'click', blue) ;}); function red () {this. className = "red"; addEvent (box, 'click', blue);} function blue () {this. className = "blue"; addEvent (box, 'click', red);} // when switching continuously, the browser suddenly gets stuck and reports an error: too much recursion, too many recursion // because too many stored events are accumulated // the solution is to use up the events and immediately remove them.
According to the above Code, there is an error in the comment. The solution is as follows:
// Add the event function // obj equivalent to window // type equivalent to onload // fn equivalent to function () {} function addEvent (obj, type, fn) {// used to save the previous event var saved = null; if (typeof obj ['on' + type] = 'function ') {saved = obj ['on' + type]; // Save the previous event} obj ['on' + type] = function () {if (saved) {saved ();} fn. call (this) ;}// when switching continuously, the browser suddenly gets stuck and reports an error: too much recursion, too many recursion // because too many stored events are accumulated // solution, the event is used up, and the event function removeEvent (obj, type) is removed immediately) {if (obj ['on' + type]) {obj ['on' + type] = null ;}} addEvent (window, 'load', function () {var box = document. getElementById ("box"); // addEvent (box, 'click', function () {// this is achieved, and is executed every time, not overwritten // alert ('ss'); //}); addEvent (box, 'click', blue) ;}); function red () {this. className = "red"; removeEvent (this, 'click'); addEvent (box, 'click', blue);} function blue () {this. className = "blue"; removeEvent (this, 'click'); addEvent (box, 'click', red );}
2. W3C event processing functions
AddEventListener () and removeEventListener ()
W3C event processing functions: addEventListener () and removeEventListener ().
// Two add events and delete events that come with W3C
1. Cover the problem and solve it
window.addEventListener('load',function(){ alert('Lee');},false);window.addEventListener('load',function(){ alert('Mr.Lee');},false);window.addEventListener('load',function(){ alert('Mrs.Lee');},false);
2. Solve the Problem of shielding the same function
window.addEventListener('load',init,false);window.addEventListener('load',init,false);window.addEventListener('load',init,false);function init(){ alert('Lee');}
3. Can this be passed?
Example 1:
window.addEventListener('load',function(){ var box=document.getElementById('box'); box.addEventListener('click',function(){ alert(this); },false);},false);
Example 2:
window.addEventListener('load',function(){ var box=document.getElementById('box'); box.addEventListener('click',blue,false);},false);function red(){ this.className="red"; this.removeEventListener('click',red,false); this.addEventListener('click',blue,false);}function blue(){ this.className="blue"; this.removeEventListener('click',blue,false); this.addEventListener('click',red,false);}
4. add an additional method, will it be overwritten, or it can only be executed once.
window.addEventListener('load',function(){ var box=document.getElementById('box'); box.addEventListener('click',function(){ alert('Lee'); },false); box.addEventListener('click',blue,false);},false);
To sum up, W3C perfectly solves these problems and is very easy to use. However, IE8 and earlier browsers do not support this, but use their own events, of course, IE9 fully supports W3C's two event processing functions.
W3C can set the bubble and capture modes.
Supports W3C standard browsers to use the addEventListener (event, fn, useCapture) method when adding events. In the base, the 3rd parameter useCapture is a Boolean value to set the event to be executed during event capture, or when the event is bubbling. The W3C-compatible browser (IE) uses the attachEvent () method. This method has no relevant settings. However, the event model of IE is executed during event bubbling by default, that is, it is executed when useCapture is equal to false. Therefore, it is safer to set useCapture to false when processing events, and it is also compatible with browsers.
Event capture phase: searches for events from the top-level tag until the event target is captured ).
Event bubble stage: events start from the event target and bubble up until the top-level tag of the page.
Event propagation can be prevented:
In W3c, use the stopPropagation () method
Set cancelBubble = true in IE;
Iii. IE event processing functions
AttachEvent () and detachEvent ()
IE implements two methods similar to that in DOM: attachEvent () and detachEvent (). The two methods use the same parameters: event name and function.
When using these two groups of functions, let's talk about the difference: 1. IE does not support capture, only supports bubbling; 2. duplicate functions cannot be blocked when adding events to IE; 3. in IE, this points to a window rather than a DOM object. 4. In traditional events, IE cannot accept event objects, but attchEvent can be used, but there are some differences.
1. The coverage problem is solved, but it is different. The result is Mrs. Lee, Mr. Lee, and finally Lee.
window.attachEvent('onload',function(){ alert('Lee');});window.attachEvent('onload',function(){ alert('Mr.Lee');});window.attachEvent('onload',function(){ alert('Mrs.Lee');});
2. The problem of shielding the same function has not been solved.
window.attachEvent('onload',init);window.attachEvent('onload',init);function init(){ alert('Lee');}
3. Can this be passed? No, this indicates window. The call method is required.
window.attachEvent('onload',function(){ var box=document.getElementById('box'); box.attachEvent('onclick',function(){ //alert(this===box); alert(this===window); //true });});
The following method is to use window. event. srcElement. The Code is as follows:
window.attachEvent('onload',function(){ var box=document.getElementById('box'); box.attachEvent('onclick',blue);});function red(){ var that=window.event.srcElement; that.className="red"; that.detachEvent('onclick',red); that.attachEvent('onclick',blue);}function blue(){ var that=window.event.srcElement; that.className="blue"; that.detachEvent('onclick',blue); that.attachEvent('onclick',red);}
4. add an additional method and check whether the method will be overwritten or executed only once.
In traditional binding, IE cannot accept event objects by passing parameters like W3C, but it is acceptable to use attachEvent.
Window. attachEvent ('onload', function () {var box = document. getElementById ('box'); box. onclick = function (evt) {// the traditional method IE cannot obtain evt alert (evt) through parameters; // undefined} box. attachEvent ('onclick', function (evt) {alert (evt); // object alert (evt. type); // click alert (evt. srcElement. tagName); // DIV alert (window. event. srcElement. tagName); // DIV });});
Cross-browser compatibility
Add events across browsers
function addEvent(obj,type,fn){ if(obj.addEventListener){ obj.addEventListener(type,fn,false); }else if(obj.attachEvent){ obj.attachEvent('on'+type,fn); }}
Cross-browser removal event
function removeEvent(obj,type,fn){ if(obj.removeEventListener){ obj.removeEventListener(type,fn,false); }else if(obj.detachEvent){ obj.detachEvent('on'+type,fn); }}
Cross-browser retrieval of target objects
function getTarget(evt){ if(evt.target){ return evt.target; }else if(window.event.srcElement){ return window.event.srcElement; }}
Call method:
addEvent(window,'load',function(){ var box=document.getElementById('box'); addEvent(box,'click',blue);});function red(evt){ var that=getTarget(evt); that.className="red"; removeEvent(that,'click',red); addEvent(that,'click',blue);}function blue(evt){ var that=getTarget(evt); that.className="blue"; removeEvent(that,'click',blue); addEvent(that,'click',red);}
4. Additional event objects
RelatedTarget event
A relatedTarget event in w3c.
For example:
AddEvent (window, 'load', function () {var box = document. getElementById ('box'); addEvent (box, 'mouseover', function (evt) {alert (evt. relatedTarget); // get the closest DOM object to the box}); addEvent (box, 'mouseout', function (evt) {alert (evt. relatedTarget); // remove the nearest DOM object from the box });});
IE provides the fromElement and toElement attributes used for migration and removal, respectively, corresponding to mouseover and mouseout.
AddEvent (window, 'load', function () {var box = document. getElementById ('box'); addEvent (box, 'mouseover', function () {alert (window. event. fromElement. tagName); // get the DOM object closest to the box}); addEvent (box, 'mouseout', function () {alert (window. event. toElement. tagName); // remove the nearest DOM object from the box });});
PS: fromElement and toElement have no meaning if they correspond to the opposite mouse event.
The remaining steps are cross-browser compatibility:
function getTarget(evt){ var e=evt || window.event; if(e.srcElment){ //IE if(e.type=='mouseover'){ return e.fromElement.tagName; }else if(e.type="mouseout"){ return e.toElement.tagName; } }else if(e.relatedTarget){ //w3c return e.relatedTarget; }}
Shield jump operations
The default action of canceling an event is to return false.
link.onclick=function(){ alert('Lee'); return false;}
PS: Although return false; can implement this function, there is a vulnerability.
First, it must be written to the end. As a result, after the winning code is executed, return false may not be executed;
Second, if return false is written to the beginning, the subsequent custom operations will become invalid.
So the best way is to stop the default behavior at the beginning, and the subsequent code can be executed.
Link. onclick = function (evt) {evt. preventDefault; // w3c, blocking default behavior alert ('lil');} link. onclick = function (evt) {window. event. returnValue = false; // IE, blocks the default behavior alert ('lil ');}
Cross-browser compatibility:
function preDef(evt){ var e=evt || window.event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue=false; }}
Right-click contextmenu
Compatibility:
function preDef(evt){ var e=evt || window.event; if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue=false; }}addEvent(window,"load",function(){ var body=document.getElementsByTagName('body')[0]; addEvent(body,'contextmenu',function(evt){ preDef(evt); })});
PS: contextmenu events are frequently used, which directly leads to stable browser compatibility.
Events Before uninstallation: beforeunload
This event can help you give a corresponding prompt when you leave this page, "exit" or "return" operation.
addEvent(window,'beforeonload',function(){ preDef(evt);});
Mouse wheel (mousewheel) and DOMMouseScroll
Used to obtain the distance between the cursor and the scroll wheel
AddEvent (document, 'mousewheel ', function (evt) {// non-Firefox alert (getWD (evt) ;}); addEvent (document, 'dommousescroll', function (evt) {// Firefox alert (getWD (evt) ;}); function getWD (evt) {var e = evt | window. event; if (e. wheelDelta) {return e. wheelDelta;} else if (e. detail) {// Firefox return-evt. detail * 30 ;}}
PS: through browser detection, it can be determined that Firefox only executes DOMMouseScroll.
DOMContentLoaded event and readystatechange event
DOMContentLoaded event and readystatechange event are related to DOM loading events.
Articles you may be interested in:
- Javascript event stream and event binding
- Div + css + js simulate tab switching effect event binding IE, firefox compatible
- JS event binding function code
- Introduction to event binding in JavaScript
- Simple Example of js mouse pulley rolling event binding (compatible with mainstream browsers)
- Deep understanding of JS event binding
- Detailed description of event binding using event transmitter mode in Node. js
- The js event binding shortcut key uses ctrl + k as an example.