javascript事件綁定學(xué)習(xí)要點
來源:易賢網(wǎng) 閱讀:788 次 日期:2016-07-21 15:30:37
溫馨提示:易賢網(wǎng)小編為您整理了“javascript事件綁定學(xué)習(xí)要點”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了javascript事件綁定學(xué)習(xí)要點,主要包含下面四個方面1.傳統(tǒng)事件綁定的問題,2.W3C事件處理函數(shù),3.IE事件處理函數(shù),4.事件對象的其他補充,有需要的小伙伴可以參考下

事件綁定分為兩種:一種是傳統(tǒng)事件綁定(內(nèi)聯(lián)模型,腳本模型),一種是現(xiàn)代事件綁定(DOM2級模型)?,F(xiàn)代事件綁定在傳統(tǒng)綁定上提供了更強大更方便的功能。

一 傳統(tǒng)事件綁定的問題

傳統(tǒng)事件綁定中的內(nèi)聯(lián)模型不做討論,基本很少去用。先來看一下腳本模型,腳本模型將一個函數(shù)賦值給一個事件處理函數(shù)。傳統(tǒng)綁定如:

window.onload=function(){

 var box=document.getElementById('box');

 box.onclick = function(){

  alert('Lee');

 };

};

問題一:一個事件處理函數(shù)觸發(fā)兩次事件

如果一個頁面有兩個或者多個js,并且第一個js是第一個程序開發(fā)的,第二個js是第二個程序員開發(fā)的。第一個window.onload被覆蓋了,如

window.onload=function(){

 alert('Lee');

};

window.onload=function(){

 alert('Mr.lee');

結(jié)果只是打印了 Mr.lee

其實是有辦法解決這個問題的,看下面這兩種形式。

a:

alert(window.onload);//一開始沒有注冊window.onload,那么就是null

window.onload=function(){

 alert('Lee');

};

alert(window.onload);//如果已經(jīng)有window.onload,打印的是函數(shù)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);//如果已經(jīng)有window.onload,所有瀏覽器都會顯示function

window.onload=function(){

 alert('Mr.lee');

}

所以解決辦法有了。

window.onload=function(){

 alert('Lee');

};

if(typeof window.onload=='function'){

 var saved=null;//保存上一個事件對象

 saved=window.onload;

}

//saved 就是window.onload,saved()相當(dāng)于window.onload(),但是window.onload()不能執(zhí)行的

//所以saved()相當(dāng)于window.onload=function(){}

window.onload=function(){

 if(saved){

  saved();//執(zhí)行上一個事件 window.onload=function(){}

 }

 alert('Mr.lee'); //執(zhí)行本事件

}

問題二:事件切換器

切換一個id為box的div,讓里面的背景red與blue直接切換,并且切換之前彈框一次,如:

window.onload=function(){

 var box=document.getElementById('box');

 box.className="red";

 box.onclick=function(){

  alert('Lee'); //只執(zhí)行了一次

  blue.call(this);//通過匿名函數(shù)執(zhí)行某一函數(shù),那么里面的this就是代表的window,所以可以通過call傳遞

 };

}

function blue(){

 this.className="blue";

 this.onclick=red;

}

function red(){

 this.className="red";

 this.onclick=blue;

}

上面的代碼雖然實現(xiàn)了切換功能,但是彈框只執(zhí)行了一次。

//添加事件函數(shù)

//obj相當(dāng)于window

//type相當(dāng)于onload

//fn相當(dāng)于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(){ //目的達(dá)到,每次都執(zhí)行了,沒有被覆蓋

 // alert('ss');

 //});

 addEvent(box,'click',blue);

});

function red(){

 this.className="red";

 addEvent(box,'click',blue);

}

function blue(){

 this.className="blue";

 addEvent(box,'click',red);

}

//當(dāng)不停的切換的時候,瀏覽器突然卡死,并且報錯:too much recursion,太多的遞歸

//因為積累了太多的保存的事件

//解決方案,就是用完的事件,就立刻移除掉

按照上面的代碼出現(xiàn)了注釋中的錯誤,解決的辦法如下:

//添加事件函數(shù)

//obj相當(dāng)于window

//type相當(dāng)于onload

//fn相當(dāng)于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);

 }

}

//當(dāng)不停的切換的時候,瀏覽器突然卡死,并且報錯:too much recursion,太多的遞歸

//因為積累了太多的保存的事件

//解決方案,就是用完的事件,就立刻移除掉

//移除事件函數(shù)

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(){ //目的達(dá)到,每次都執(zhí)行了,沒有被覆蓋

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

}

二 W3C事件處理函數(shù)

addEventListener()與removeEventListener()

W3C事件處理函數(shù)兩個,addEventListener()與removeEventListener()。

//W3C自帶的兩個添加事件和刪除事件

1.覆蓋問題,解決

window.addEventListener('load',function(){

 alert('Lee');

},false);

window.addEventListener('load',function(){

 alert('Mr.Lee');

},false);

window.addEventListener('load',function(){

 alert('Mrs.Lee');

},false);

2.相同函數(shù)屏蔽的問題,解決

window.addEventListener('load',init,false);

window.addEventListener('load',init,false);

window.addEventListener('load',init,false);

function init(){

 alert('Lee');

}

3.是否可以傳遞this,解決

例子1:

window.addEventListener('load',function(){

 var box=document.getElementById('box');

 box.addEventListener('click',function(){

  alert(this);

 },false);

},false);

例子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.添加一個額外的方法,會不會被覆蓋,或者只能執(zhí)行一次,解決

window.addEventListener('load',function(){

 var box=document.getElementById('box');

 box.addEventListener('click',function(){

  alert('Lee');

 },false);

 box.addEventListener('click',blue,false);

},false);

綜上所述:W3C是比較完美的解決了這些問題,非常好用,但是IE8和之前的瀏覽器并不支持,而是采用了自己的事件,當(dāng)然IE9已經(jīng)完全支持了W3C的這兩個事件處理函數(shù)。

W3C可以設(shè)置冒泡和捕獲方式。

支持W3C標(biāo)準(zhǔn)的瀏覽器在添加事件時用addEventListener(event,fn,useCapture)方法,基中第3個參數(shù)useCapture是一個Boolean值,用來設(shè)置事件是在事件捕獲時執(zhí)行,還是事件冒泡時執(zhí)行。而不兼容W3C的瀏覽器(IE)用attachEvent()方法,此方法沒有相關(guān)設(shè)置,不過IE的事件模型默認(rèn)是在事件冒泡時執(zhí)行的,也就是在useCapture等于false的時候執(zhí)行,所以把在處理事件時把useCapture設(shè)置為false是比較安全,也實現(xiàn)兼容瀏覽器的效果。

事件捕獲階段:事件從最上一級標(biāo)簽開始往下查找,直到捕獲到事件目標(biāo)(target)。

事件冒泡階段:事件從事件目標(biāo)(target)開始,往上冒泡直到頁面的最上一級標(biāo)簽。

事件的傳播是可以阻止的:

在W3c中,使用stopPropagation()方法

在IE下設(shè)置cancelBubble = true;

三.IE事件處理函數(shù)

attachEvent()和detachEvent()

IE實現(xiàn)了與DOM中類似的兩個方法:attachEvent()和detachEvent()。這兩個方法接受相同的參數(shù):事件名稱和函數(shù)。

在使用這兩組函數(shù)的時候,先把區(qū)別說一下:1.IE不支持捕獲,只支持冒泡;2.IE添加事件不能屏蔽重復(fù)的函數(shù);3.IE中的this指向的是window而不是DOM對象。4.在傳統(tǒng)事件上,IE是無法接受到event對象的,但使用了attchEvent卻可以,但有些區(qū)別。

1.覆蓋問題,解決了,但有不同,結(jié)果是Mrs.Lee,Mr.Lee,最后是Lee

window.attachEvent('onload',function(){

 alert('Lee');

});

window.attachEvent('onload',function(){

 alert('Mr.Lee');

});

window.attachEvent('onload',function(){

 alert('Mrs.Lee');

});

2.相同函數(shù)屏蔽的問題,未解決。

window.attachEvent('onload',init);

window.attachEvent('onload',init);

function init(){

 alert('Lee');

}

3.是否可以傳遞this,不能,this指的是window。需要用call方法。

window.attachEvent('onload',function(){

 var box=document.getElementById('box');

 box.attachEvent('onclick',function(){

  //alert(this===box);

  alert(this===window); //true

 });

});

下面還有辦法就是通過window.event.srcElement。代碼如下:

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.添加一個額外的方法,會不會被覆蓋,或者只能執(zhí)行一次,解決。

在傳統(tǒng)綁定上,IE是無法像W3C那樣通過傳參接受event對象,但是使用attachEvent()卻可以。

window.attachEvent('onload',function(){

 var box=document.getElementById('box');

 box.onclick=function(evt){ //傳統(tǒng)方法IE無法通過參數(shù)獲取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

 });

});

跨瀏覽器的兼容

跨瀏覽器添加事件

function addEvent(obj,type,fn){

 if(obj.addEventListener){

  obj.addEventListener(type,fn,false);

 }else if(obj.attachEvent){

  obj.attachEvent('on'+type,fn);

 }

}

跨瀏覽器移除事件

function removeEvent(obj,type,fn){

 if(obj.removeEventListener){

  obj.removeEventListener(type,fn,false);

 }else if(obj.detachEvent){

  obj.detachEvent('on'+type,fn);

 }

}

跨瀏覽器獲取目標(biāo)對象

function getTarget(evt){

 if(evt.target){

  return evt.target;

 }else if(window.event.srcElement){

  return window.event.srcElement;

 }

}

調(diào)用方式:

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,分別對應(yīng)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如果分別對應(yīng)相反的鼠標(biāo)事件,沒有任何意義。

剩下要做的就是跨瀏覽器兼容操作:

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;

 }

}

屏蔽跳轉(zhuǎn)操作

取消事件的默認(rèn)行為有一種不規(guī)范的做法,就是返回false。

link.onclick=function(){

 alert('Lee');

 return false;

}

PS:雖然return false;可以實現(xiàn)這個功能,但是有漏洞。

第一:必須寫到最后,這樣導(dǎo)致中獎的代碼執(zhí)行后,有可能執(zhí)行不到return false;

第二:return false 寫到最前那么之后的自定義操作就失效了。

所以最好的辦法應(yīng)該是在最前面就阻止默認(rèn)行為,并且后面的代碼還可以執(zhí)行。

link.onclick=function(evt){

 evt.preventDefault;//w3c,阻止默認(rèn)行為

 alert('Lee');

}

link.onclick=function(evt){

 window.event.returnValue=false;//IE,阻止默認(rèn)行為

 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事件很常用,這直接導(dǎo)致瀏覽器兼容性較為穩(wěn)定。

卸載前事件:beforeunload

這個事件可以幫助在離開本頁的時候給出相應(yīng)的提示,“離開”或者“返回”操作。

addEvent(window,'beforeonload',function(){

 preDef(evt);

});

鼠標(biāo)滾輪(mousewheel)和DOMMouseScroll

用于獲取鼠標(biāo)上下滾輪的距離

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:通過瀏覽器檢測可以確定火狐只執(zhí)行DOMMouseScroll。

DOMContentLoaded事件和readystatechange事件

DOMContentLoaded事件和readystatechange事件,有關(guān)DOM加載方面的事件。

更多信息請查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機網(wǎng)站地址:javascript事件綁定學(xué)習(xí)要點
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報警專用圖標(biāo)