Maison  >  Article  >  interface Web  >  Points d'apprentissage de liaison d'événement JavaScript_connaissances de base

Points d'apprentissage de liaison d'événement JavaScript_connaissances de base

WBOY
WBOYoriginal
2016-05-16 15:11:311085parcourir

La liaison d'événements est divisée en deux types : l'une est la liaison d'événements traditionnelle (modèle en ligne, modèle de script) et l'autre est la liaison d'événements moderne (modèle de niveau DOM2). La liaison d'événements moderne offre des fonctions plus puissantes et plus pratiques que la liaison traditionnelle.

1 Problèmes avec la liaison d'événements traditionnelle

Le modèle en ligne dans la liaison d'événements traditionnelle ne sera pas discuté et est rarement utilisé. Jetons d'abord un coup d'œil au modèle de script. Le modèle de script attribue une fonction à une fonction de gestion d'événements. Reliure traditionnelle telle que :

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



Problème 1 : Une fonction de gestion d'événements déclenche deux événements

Si une page contient deux js ou plus et que le premier js est développé par le premier programmeur, le second js est développé par le deuxième programmeur. Le premier window.onload est écrasé, tel que

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

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

Le résultat vient d'être imprimé Mr.lee

En fait, il existe des moyens de résoudre ce problème. Jetez un œil aux deux formulaires suivants.
une :

alert(window.onload);//一开始没有注册window.onload,那么就是null

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

alert(window.onload);//如果已经有window.onload,打印的是函数function

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

b :

alert(typeof window.onload);//一开始没有window.onolad,旧版火狐显示undefined,新版显示object,

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

alert(typeof window.onload);//如果已经有window.onload,所有浏览器都会显示function

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

Il existe donc une solution.

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

if(typeof window.onload=='function'){
 var saved=null;//保存上一个事件对象
 saved=window.onload;
}

//saved 就是window.onload,saved()相当于window.onload(),但是window.onload()不能执行的
//所以saved()相当于window.onload=function(){}

window.onload=function(){
 if(saved){
  saved();//执行上一个事件 window.onload=function(){}
 }
 alert('Mr.lee'); //执行本事件
}

Question 2 : Sélecteur d'événements
Basculez un div avec l'ID de la boîte, laissez l'arrière-plan rouge et bleu à l'intérieur changer directement et faites apparaître la boîte une fois avant de changer, comme :

window.onload=function(){
 var box=document.getElementById('box');
 box.className="red";
 box.onclick=function(){
  alert('Lee'); //只执行了一次
  blue.call(this);//通过匿名函数执行某一函数,那么里面的this就是代表的window,所以可以通过call传递
 };
}

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

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

Bien que le code ci-dessus implémente la fonction de commutation, la boîte contextuelle n'est exécutée qu'une seule fois.

//添加事件函数
//obj相当于window
//type相当于onload
//fn相当于function(){}
function addEvent(obj,type,fn){
 //用于保存上一个事件
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];//保存上一个事件
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}
addEvent(window,'load',function(){
 var box=document.getElementById("box");
 //addEvent(box,'click',function(){ //目的达到,每次都执行了,没有被覆盖
 // alert('ss');
 //});
 addEvent(box,'click',blue);
});

function red(){
 this.className="red";
 addEvent(box,'click',blue);
}

function blue(){
 this.className="blue";
 addEvent(box,'click',red);
}

//当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归
//因为积累了太多的保存的事件
//解决方案,就是用完的事件,就立刻移除掉

Selon le code ci-dessus, une erreur s'est produite dans le commentaire. La solution est la suivante :

//添加事件函数
//obj相当于window
//type相当于onload
//fn相当于function(){}
function addEvent(obj,type,fn){
 //用于保存上一个事件
 var saved=null;
 if(typeof obj['on'+type]=='function'){
  saved=obj['on'+type];//保存上一个事件
 }
 obj['on'+type]=function(){
  if(saved){
   saved();
  }
  fn.call(this);
 }
 
}


//当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归
//因为积累了太多的保存的事件
//解决方案,就是用完的事件,就立刻移除掉


//移除事件函数
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(){ //目的达到,每次都执行了,没有被覆盖
 // 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);
}

Deux fonctions de gestion des événements du W3C
addEventListener() et removeEventListener()
Il existe deux fonctions de gestion des événements du W3C, addEventListener() et removeEventListener().

//W3C est livré avec deux événements d'ajout et de suppression
1. Problème de couverture, résolu

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

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

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

2. Le problème du blocage de la même fonction est résolu

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

3. Est-il possible de passer cela et de le résoudre
Exemple 1 :

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

Exemple 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. Ajoutez une méthode supplémentaire. Sera-t-elle écrasée ou ne pourra-t-elle être exécutée qu'une seule fois ?

window.addEventListener('load',function(){
 var box=document.getElementById('box');
 box.addEventListener('click',function(){
  alert('Lee');
 },false);
 box.addEventListener('click',blue,false);
},false);
Pour résumer : le W3C a parfaitement résolu ces problèmes et est très simple à utiliser. Cependant, IE8 et les navigateurs précédents ne le prennent pas en charge, mais utilisent leurs propres événements. Bien sûr, IE9 a entièrement pris en charge cela du W3C. Deux fonctions de gestion d'événements.

Le W3C peut définir des méthodes de bouillonnement et de capture.

Les navigateurs prenant en charge la norme W3C utilisent la méthode addEventListener(event,fn,useCapture) lors de l'ajout d'événements. Le troisième paramètre useCapture dans la base est une valeur booléenne, qui est utilisée pour définir si l'événement est exécuté lors de la capture d'événement ou lorsque l'événement se produit. Exécuté lors du trempage. Les navigateurs qui ne sont pas compatibles avec le W3C (IE) utilisent la méthode attachEvent(). Cette méthode n'a pas de paramètres pertinents. Cependant, le modèle d'événement d'IE est exécuté par défaut lorsque l'événement apparaît, c'est-à-dire lorsque useCapture est égal à false, donc. mettez-le dedans Il est plus sûr de définir useCapture sur false lors de la gestion des événements, et cela assure également la compatibilité du navigateur.

Phase de capture d'événement : l'événement commence à partir de l'étiquette de niveau supérieur et recherche vers le bas jusqu'à ce que la cible de l'événement (cible) soit capturée.

Étape de bouillonnement d'événement : l'événement commence à partir de la cible de l'événement (cible) et remonte jusqu'à l'étiquette de niveau supérieur de la page.
La propagation des événements peut être stoppée :
Dans le W3c, utilisez la méthode stopPropagation()
Définissez CancelBubble = true sous IE

3. Fonction de gestion des événements IE

attachEvent() et detachEvent()

IE implémente deux méthodes similaires à celles du DOM : attachEvent() et detachEvent(). Les deux méthodes acceptent les mêmes paramètres : nom de l'événement et fonction.

Lors de l'utilisation de ces deux ensembles de fonctions, parlons d'abord des différences : 1. IE ne prend pas en charge la capture, seulement le bouillonnement ; 2. L'ajout d'événements dans IE ne peut pas bloquer les fonctions en double ; 3. cela dans IE pointe vers une fenêtre au lieu d'un ; Objet DOM. 4. Dans les événements traditionnels, IE ne peut pas accepter les objets événement, mais l'utilisation de attchEvent le peut, mais il existe quelques différences.

1. Le problème de couverture est résolu, mais il y a des différences. Le résultat est Mme Lee, M. Lee et enfin Lee

.

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

window.attachEvent('onload',function(){
 alert('Mr.Lee');
});
window.attachEvent('onload',function(){
 alert('Mrs.Lee');
});

2. Le problème du blocage de la même fonction n'a pas été résolu.

window.attachEvent('onload',init);
window.attachEvent('onload',init);

function init(){
 alert('Lee');
}

3. Cela peut-il être adopté ? Non, cela fait référence à la fenêtre. Besoin d'utiliser la méthode d'appel.

window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.attachEvent('onclick',function(){
  //alert(this===box);
  alert(this===window); //true
 });
});
La méthode suivante consiste à transmettre window.event.srcElement. Le code est le suivant :

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. Ajoutez une méthode supplémentaire. Sera-t-elle écrasée ou ne pourra-t-elle être exécutée qu'une seule fois ?

Dans la liaison traditionnelle, IE ne peut pas accepter les objets événement via le passage de paramètres comme le W3C, mais cela peut être fait en utilisant attachEvent().

 window.attachEvent('onload',function(){
 var box=document.getElementById('box');
 box.onclick=function(evt){ //传统方法IE无法通过参数获取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
 });
});

Compatibilité entre navigateurs

Événements multi-navigateurs

function addEvent(obj,type,fn){
 if(obj.addEventListener){
  obj.addEventListener(type,fn,false);
 }else if(obj.attachEvent){
  obj.attachEvent('on'+type,fn);
 }
}

Événement de suppression multi-navigateurs

function removeEvent(obj,type,fn){
 if(obj.removeEventListener){
  obj.removeEventListener(type,fn,false);
 }else if(obj.detachEvent){
  obj.detachEvent('on'+type,fn);
 }
}
Obtenir l'objet cible dans les navigateurs

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

调用方式:

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);
}

四.事件对象的其他补充

relatedTarget事件

w3c中的一个relatedTarget事件。
例如:

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(evt){
  alert(evt.relatedTarget); //得到移入box最近的那个DOM对象
 });
 
 addEvent(box,'mouseout',function(evt){
  alert(evt.relatedTarget); //从box移出最近的那个DOM对象
 });
});

IE提供了两组分别用于移入移出的属性fromElement和toElement,分别对应mouseover和mouseout。

addEvent(window,'load',function(){
 var box=document.getElementById('box');
 addEvent(box,'mouseover',function(){
  alert(window.event.fromElement.tagName); //得到移入box最近的那个DOM对象
 });
 
 addEvent(box,'mouseout',function(){
  alert(window.event.toElement.tagName); //从box移出最近的那个DOM对象
 });
});

PS:fromElement和toElement如果分别对应相反的鼠标事件,没有任何意义。

剩下要做的就是跨浏览器兼容操作:

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;
 }
}

屏蔽跳转操作

取消事件的默认行为有一种不规范的做法,就是返回false。

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

PS:虽然return false;可以实现这个功能,但是有漏洞。
第一:必须写到最后,这样导致中奖的代码执行后,有可能执行不到return false;
第二:return false 写到最前那么之后的自定义操作就失效了。
所以最好的办法应该是在最前面就阻止默认行为,并且后面的代码还可以执行。

link.onclick=function(evt){
 evt.preventDefault;//w3c,阻止默认行为
 alert('Lee');
}

link.onclick=function(evt){
 window.event.returnValue=false;//IE,阻止默认行为
 alert('Lee');
}

那么跨浏览器的兼容:

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

右键菜单contextmenu
兼容:

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事件很常用,这直接导致浏览器兼容性较为稳定。

卸载前事件:beforeunload
这个事件可以帮助在离开本页的时候给出相应的提示,“离开”或者“返回”操作。

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

鼠标滚轮(mousewheel)和DOMMouseScroll
用于获取鼠标上下滚轮的距离

addEvent(document,'mousewheel',function(evt){ //非火狐
 alert(getWD(evt));
});

addEvent(document,'DOMMouseScroll',function(evt){ //火狐
 alert(getWD(evt));
});

function getWD(evt){
 var e=evt|| window.event;
 if(e.wheelDelta){
  return e.wheelDelta;
 }else if(e.detail){ //火狐
  return -evt.detail*30;
 }
}

PS:通过浏览器检测可以确定火狐只执行DOMMouseScroll。

DOMContentLoaded事件和readystatechange事件

DOMContentLoaded事件和readystatechange事件,有关DOM加载方面的事件。

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn