javascript event binding learning points

  • 2021-01-25 07:04:00
  • OfStack

Event binding is divided into two types: one is the traditional event binding (inline model, script model), the other is the modern event binding (DOM2-level model). Modern event bindings provide more powerful and convenient functions over traditional bindings.

Problems with traditional event binding

The inline model in traditional event binding is not discussed and is rarely used. Let's start with the script model, which assigns a function to an event handler. Traditional bindings such as:


window.onload=function(){
 var box=document.getElementById('box');
 box.onclick = function(){
  alert('Lee');
 };
};



Problem 1:1 an event handler fires two events

If a page has two or more js, and the first js is developed by the first program, and the second js is developed by the second programmer. The first window.onload is overwritten, as in


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

The result is only Mr.lee

There's actually a way to solve this problem. Let's look at the two forms.
a:


alert(window.onload);//1 No registration at first window.onload, It is null

window.onload=function(){
 alert('Lee');
};

alert(window.onload);// If you already have window.onload, It's a function function

window.onload=function(){
 alert('Mr.lee');
} 

b:


alert(typeof window.onload);//1 Start no window.onolad, Old versions of Firefox undefined, The new show object,

window.onload=function(){
 alert('Lee');
};

alert(typeof window.onload);// If you already have window.onload, It will be displayed in all browsers function

window.onload=function(){
 alert('Mr.lee');
}

So there's a solution.


 window.onload=function(){
 alert('Lee');
};

if(typeof window.onload=='function'){
 var saved=null;// Save on 1 Event objects 
 saved=window.onload;
}

//saved  is window.onload,saved() The equivalent of window.onload(), but window.onload() unexecutable 
// so saved() The equivalent of window.onload=function(){}

window.onload=function(){
 if(saved){
  saved();// To perform the 1 An event  window.onload=function(){}
 }
 alert('Mr.lee'); // Execute this event 
}

Problem 2: Event switcher
Switch 1 div with box as id, and switch the background red and blue directly, and pop-up once before switching, such as:


window.onload=function(){
 var box=document.getElementById('box');
 box.className="red";
 box.onclick=function(){
  alert('Lee'); // Only performed 1 time 
  blue.call(this);// Executes something through an anonymous function 1 Delta function, so the inner delta this Is the representative of window, So you can go through call pass 
 };
}

function blue(){
 this.className="blue";
 this.onclick=red;
 
}

function red(){
 this.className="red";
 this.onclick=blue;
}

The above code implements the toggle function, but the popup box only executes once.


// Adding Event Functions 
//obj The equivalent of window
//type The equivalent of onload
//fn The equivalent of function(){}
function addEvent(obj,type,fn){
 // For preservation 1 An event 
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];// Save on 1 An event 
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}
addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ // The goal is achieved. Every time it is executed, it is 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, the browser suddenly freezes and returns an error: too much recursion, Too much recursion 
// Because there are too many saved events 
// The solution is to remove the used events as soon as possible 

There is an error in the comment according to the above code. The solution is as follows:


// Adding Event Functions 
//obj The equivalent of window
//type The equivalent of onload
//fn The equivalent of function(){}
function addEvent(obj,type,fn){
 // For preservation 1 An event 
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];// Save on 1 An event 
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}


// When switching, the browser suddenly freezes and returns an error: too much recursion, Too much recursion 
// Because there are too many saved events 
// The solution is to remove the used events as soon as possible 


// Remove event function 
function removeEvent(obj,type){
 if(obj['on'+type]){
  obj['on'+type]=null;
 }
}


addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ // The goal is achieved. Every time it is executed, it is 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 handler
With removeEventListener addEventListener () ()
Two W3C event handlers, addEventListener() and removeEventListener().

//W3C has two add events and delete events
1. Coverage problem, solved


window.addEventListener('load',function(){
 alert('Lee');
},false);

window.addEventListener('load',function(){
 alert('Mr.Lee');
},false);

window.addEventListener('load',function(){
 alert('Mrs.Lee');
},false);

2. The same function shielding problem, solved


window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
function init(){
 alert('Lee');
}

3. Can we pass this
Example 1:


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

0

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 extra method, will it be overridden, or can only be executed once, resolved


window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',function(){
  alert('Lee');
 },false);
 box.addEventListener('click',blue,false);
},false);

To summarize: W3C is a relatively perfect solution to these problems, very easy to use, but IE8 and previous browsers do not support, but use their own events, of course, IE9 has fully supported W3C these two event handlers.

W3C can set the bubble and capture mode.

Browsers that support W3C use the addEventListener(event,fn,useCapture) method when adding events. The third parameter, useCapture, is an Boolean value, which sets whether the event is executed when the event is caught or when the event is bubbling. And incompatible W3C browser (IE) using attachEvent () method, this method is not related to setup, but the default IE event models is performed when event bubbling, namely when useCapture equals false execution, so when processing events set useCapture to false is safer, and the effect of implementation browser compatibility.

Event capture phase: Events are searched from the topmost 1-level tag down until the event target (target) is captured.
Event bubbling phase: Events start at the event target (target) and bubble up to the top 1-level tag on the page.
The propagation of the event can be prevented:
In W3c, the stopPropagation() method is used
Set cancelBubble = true under IE;

3.IE event handler

attachEvent () and detachEvent ()
IE implements two methods similar to those in DOM: attachEvent() and detachEvent(). Both methods take the same arguments: the event name and the function.

1.IE does not support capture, only bubbling; 2.IE does not support capture, only bubbling. 2.IE add events cannot mask duplicate functions; 3. this in IE refers to window and not to DOM objects. 4. In traditional events, IE does not accept event objects, but using attchEvent does, with some differences.

1. Coverage problem solved, but with a difference, the result is Mrs.Lee, Mr.Lee, and finally Lee


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

3

2. The same function masking problem, not resolved.


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

4

3. Can you pass this? No, this means window. The call method is required.


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

5

The next option is window.event.srcElement. The code is as follows:


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

6

4. Add an extra method, will it be overridden, or can only be executed once, resolved.

In traditional bindings, IE cannot accept event objects by passing arguments as W3C does, but using attachEvent() can.


 window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.onclick=function(evt){ // The traditional method IE Cannot be obtained from a parameter evt
  alert(evt);//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);
 }
}

Removes events across browsers


window.onload=function(){
 alert('Lee');
};

window.onload=function(){
 alert('Mr.lee');
} 

9

Get the target object across browsers


function getTarget(evt){
 if(evt.target){
  return evt.target;
 }else if(window.event.srcElement){
  return window.event.srcElement;
 }
}

Call mode:


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 additions to event objects

relatedTarget event

relatedTarget event in w3c.
Such as:


addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(evt){
  alert(evt.relatedTarget); // Get moving box The nearest one DOM object 
 });
 
 addEvent(box,'mouseout',function(evt){
  alert(evt.relatedTarget); // from box Move out the nearest one DOM object 
 });
});

IE provides two sets of migration in and out attributes fromElement and toElement, corresponding to mouseover and mouseout, respectively.


addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(){
  alert(window.event.fromElement.tagName); // Get moving box The nearest one DOM object 
 });
 
 addEvent(box,'mouseout',function(){
  alert(window.event.toElement.tagName); // from box Move out the nearest one DOM object 
 });
});

PS:fromElement and toElement have no meaning if they correspond to opposite mouse events.

All that's left to do is work across browsers:


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

A non-standard way to cancel the default behavior of an event is to return false.


link.onclick=function(){
 alert('Lee');
 return false;
}

PS: Although return, false; You can do this, but there are bugs.
1. The code must be written to the end, so that the winning code may not execute return false after execution.
return: false writes to the very top, then any subsequent custom operations will fail.
So the best thing to do is to block the default behavior up front and let the code execute later.


link.onclick=function(evt){
 evt.preventDefault;//w3c, Preventing default behavior 
 alert('Lee');
}

link.onclick=function(evt){
 window.event.returnValue=false;//IE, Preventing default behavior 
 alert('Lee');
}

So cross-browser compatibility:


function preDef(evt){
 var e=evt || window.event;
 if(e.preventDefault){
  e.preventDefault();
 }else{
  e.returnValue=false;
 }
}

Right click menu contextmenu
Compatible with:


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: The contextmenu event is very common, which directly results in stable browser compatibility.

Pre-uninstall event: beforeunload
This event helps to indicate when leaving the page, "leave" or "return" actions.


addEvent(window,'beforeonload',function(){
 preDef(evt);
});

Mouse Wheel (mousewheel) and DOMMouseScroll
Used to get the distance of the mouse wheel up and down


addEvent(document,'mousewheel',function(evt){ // The 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: Browser checks confirm that Firefox only executes DOMMouseScroll.

DOMContentLoaded event and readystatechange event

DOMContentLoaded event and readystatechange event, events about the loading aspect of DOM.


Related articles: