欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解javascript中的事件處理

 更新時(shí)間:2015年11月06日 14:06:28   投稿:lijiao  
這篇文章主要介紹了javascript的事件處理,需要的朋友可以參考下

一.事件傳播機(jī)制

  客戶端JavaScript程序(就是瀏覽器啦)采用了異步事件驅(qū)動(dòng)編程模型。當(dāng)文檔、瀏覽器、元素或與之相關(guān)的對(duì)象發(fā)生某些有趣的事情時(shí),Web瀏覽器就會(huì)產(chǎn)生事件(event)。如果JavaScript應(yīng)用程序關(guān)注特定類(lèi)型的事件,那么它可以注冊(cè)當(dāng)這類(lèi)事件發(fā)生時(shí)要調(diào)用的一個(gè)或多個(gè)函數(shù)。當(dāng)然了,這種風(fēng)格并非Web編程獨(dú)有,所有使用圖形用戶界面的應(yīng)用程序都采用了它。

既然要詳解事件處理,那我們先從幾個(gè)基礎(chǔ)概念說(shuō)起吧:

    ①事件類(lèi)型(event type):是一個(gè)用來(lái)說(shuō)明發(fā)生什么類(lèi)型事件的字符串。例如,“mousemove”表示用戶移動(dòng)鼠標(biāo),“keydown”表示鍵盤(pán)上某個(gè)鍵被按下。事件類(lèi)型只是一個(gè)字符串,有時(shí)候又稱(chēng)之為事件名字(event name);

    ②事件目標(biāo)(event target):是發(fā)生事件或與之相關(guān)的對(duì)象。Window、Document和Element對(duì)象是最常見(jiàn)的事件目標(biāo)。當(dāng)然,AJAX中的XMLHttpRequest對(duì)象也是一個(gè)事件目標(biāo);

    ③事件處理程序(event handler):是處理或響應(yīng)事件的函數(shù),它也叫事件監(jiān)聽(tīng)程序(event listener)。應(yīng)用程序通過(guò)指明事件類(lèi)型和事件目標(biāo),在Web瀏覽器中注冊(cè)它們的事件處理函數(shù)。

    ④事件對(duì)象(event object):是與特定事件相關(guān)且包含有關(guān)該事件詳細(xì)信息的對(duì)象。事件對(duì)象作為參數(shù)傳遞給事件處理函數(shù)(但是在IE8以及其之前版本中,全局變量event才是事件對(duì)象)。事件對(duì)象都有用來(lái)指定事件類(lèi)型(event type)的type屬性和指定事件目標(biāo)(event target)的target屬性(但是在IE8以及其之前版本中,用的是srcElement而非target)。當(dāng)然,不同類(lèi)型的事件還會(huì)為其相關(guān)事件對(duì)象定義一些其他的獨(dú)有屬性。例如,鼠標(biāo)事件的相關(guān)對(duì)象會(huì)包含鼠標(biāo)指針的坐標(biāo),而鍵盤(pán)事件的相關(guān)對(duì)象會(huì)包含按下的鍵和輔助鍵的詳細(xì)信息。

  以上說(shuō)完了四個(gè)基本概念。那么問(wèn)題來(lái)了——如果在一個(gè)web頁(yè)面上用鼠標(biāo)點(diǎn)擊一個(gè)元素a的某一子元素b時(shí),應(yīng)該先執(zhí)行子元素b注冊(cè)的事件處理程序還是先執(zhí)行元素a注冊(cè)的事件處理程序呢(假設(shè)元素a和它的子元素b都有注冊(cè)事件處理程序)?身為讀者的你是否想過(guò)這個(gè)問(wèn)題呢?

  這個(gè)問(wèn)題就涉及到瀏覽器中的事件傳播(event propagation)機(jī)制。相信大家都聽(tīng)說(shuō)過(guò)事件冒泡(event bubble)和事件捕獲(event capturing)吧!沒(méi)錯(cuò),它們就是瀏覽器中的事件傳播機(jī)制。無(wú)圖無(wú)真相,沒(méi)有配圖?那怎么闊以:

  看了圖之后相信你已經(jīng)大概理解了瀏覽器中的事件傳播機(jī)制了:當(dāng)一個(gè)事件發(fā)生時(shí),它會(huì)先從瀏覽器頂級(jí)對(duì)象Window一路向下傳遞,一直傳遞到觸發(fā)這個(gè)事件的那個(gè)元素,這也就是事件捕獲過(guò)程。然而,一切并沒(méi)有結(jié)束,事件又從這個(gè)元素一路向上傳遞到Window對(duì)象,這也就是事件冒泡過(guò)程(但是在IE8以及其之前版本中,事件模型并未定義捕獲過(guò)程,只有冒泡過(guò)程)。

  所以,關(guān)于上面的問(wèn)題,還得看元素a注冊(cè)的事件處理程序是在捕獲過(guò)程還是在冒泡過(guò)程了。那么到底什么是在捕獲過(guò)程注冊(cè)事件處理程序,在冒泡過(guò)程注冊(cè)事件處理程序又是怎么做的呢?這就得好好說(shuō)說(shuō)幾種注冊(cè)事件處理程序的方式了:

1. 設(shè)置HTML標(biāo)簽屬性為事件處理程序

  文檔元素的事件處理程序?qū)傩裕涿钟伞皁n”后面跟著事件名組成,例如:onclick、onmouseover。當(dāng)然了,這種形式只能為DOM元素注冊(cè)事件處理程序。實(shí)例:

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow:hidden;}
 #div2{margin:50px auto; width: 200px; height: 200px; background: green; overflow:hidden;}
 #div3{margin:50px auto; width: 100px; height: 100px; background: blue;}
 </style>
</head>
<body>
 <div id="div1" onClick="console.log('div1');">div1
 <div id="div2" oNClick="console.log('div2');">div2
 <div id="div3" onclick="console.log('div3');" onclick="console.log('div3333');">div3
 </div>
 </div>
 </div>
<script type="text/javascript">
</script>
</body>
</html>

結(jié)果(鼠標(biāo)點(diǎn)擊div3區(qū)域后):

從結(jié)果中可以看出:

  ①因?yàn)镠TML里面不區(qū)分大小寫(xiě),所以這里事件處理程序?qū)傩悦髮?xiě)、小寫(xiě)、大小混寫(xiě)均可,屬性值就是相應(yīng)事件處理程序的JavaScript代碼;

 ?、谌艚o同一元素寫(xiě)多個(gè)onclick事件處理屬性,瀏覽器只執(zhí)行第一個(gè)onclick里面的代碼,后面的會(huì)被忽略;

 ?、圻@種形式是在事件冒泡過(guò)程中注冊(cè)事件處理程序的;

2.設(shè)置JavaScript對(duì)象屬性為事件處理程序

  可以通過(guò)設(shè)置某一事件目標(biāo)的事件處理程序?qū)傩詠?lái)為其注冊(cè)相應(yīng)的事件處理程序。事件處理程序?qū)傩悦钟伞皁n”后面跟著事件名組成,例如:onclick、onmouseover。實(shí)例:

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow:hidden;}
 #div2{margin:50px auto; width: 200px; height: 200px; background: green; overflow:hidden;}
 #div3{margin:50px auto; width: 100px; height: 100px; background: blue;}
 </style>
</head>
<body>
 <div id="div1">div1
 <div id="div2">div2
 <div id="div3">div3
 </div>
 </div>
 </div>
<script type="text/javascript">
 var div1 = document.getElementById('div1');
 var div2 = document.getElementById('div2');
 var div3 = document.getElementById('div3');
  div1.onclick = function(){
    console.log('div1');
  };
  div2.onclick = function(){
    console.log('div2');
  };
  div3.onclick = function(){
    console.log('div3');
  };
  div1.onclick = function(){
    console.log('div11111');
  };

  div1.onClick = function(){
    console.log('DIV11111');
  };

</script>
</body>
</html>

結(jié)果(鼠標(biāo)點(diǎn)擊div3區(qū)域后):

 從結(jié)果中可以看出:

  ①因?yàn)镴avaScript是嚴(yán)格區(qū)分大小寫(xiě)的,所以,這種形式下屬性名只能按規(guī)定小寫(xiě);

 ?、谌艚o同一元素對(duì)象寫(xiě)多個(gè)onclick事件處理屬性,后面寫(xiě)的會(huì)覆蓋前面的(ps:這就是在修改一個(gè)對(duì)象屬性的值,屬性的值是唯一確定的);

  ③這種形式也是在事件冒泡過(guò)程中注冊(cè)事件處理程序的;

3.addEventListener()

  前兩種方式出現(xiàn)在Web初期,眾多瀏覽器都有實(shí)現(xiàn)。而addEventListener()方法是標(biāo)準(zhǔn)事件模型中定義的。任何能成為事件目標(biāo)的對(duì)象——這些對(duì)象包括Window對(duì)象、Document對(duì)象和所有文檔元素等——都定義了一個(gè)名叫addEventListener()的方法,使用這個(gè)方法可以為事件目標(biāo)注冊(cè)事件處理程序。addEventListener()接受三個(gè)參數(shù):第一個(gè)參數(shù)是要注冊(cè)處理程序的事件類(lèi)型,其值是字符串,但并不包括前綴“on”;第二個(gè)參數(shù)是指當(dāng)指定類(lèi)型的事件發(fā)生時(shí)應(yīng)該調(diào)用的函數(shù);第三個(gè)參數(shù)是布爾值,其可以忽略(某些舊的瀏覽器上不能忽略這個(gè)參數(shù)),默認(rèn)值為false。這種情況是在事件冒泡過(guò)程中注冊(cè)事件處理程序。當(dāng)其為true時(shí),就是在事件捕獲過(guò)程中注冊(cè)事件處理程序。實(shí)例:

<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title>test</title>
  <style type="text/css">
    #div1{width: 300px; height: 300px; background: red; overflow:hidden;}
    #div2{margin:50px auto; width: 200px; height: 200px; background: green; overflow:hidden;}
    #div3{margin:50px auto; width: 100px; height: 100px; background: blue;}
  </style>
</head>
<body>
  <div id="div1">div1
    <div id="div2">div2
      <div id="div3">div3
      </div>
    </div>
  </div>
<script type="text/javascript">
  var div1 = document.getElementById('div1');
  var div2 = document.getElementById('div2');
  var div3 = document.getElementById('div3');
  div1.addEventListener('click', function(){ console.log('div1-bubble'); }, false);
  div2.addEventListener('click', function(){ console.log('div2-bubble'); }, false);
  div3.addEventListener('click', function(){ console.log('div3-bubble'); }, false);
  div3.addEventListener('click', function(){ console.log('div3-bubble222'); }, false);
  div1.addEventListener('click', function(){ console.log('div1-capturing'); }, true);
  div2.addEventListener('click', function(){ console.log('div2-capturing'); }, true);
  div3.addEventListener('click', function(){ console.log('div3-capturing'); }, true);
</script>
</body>
</html>

結(jié)果(鼠標(biāo)點(diǎn)擊div3區(qū)域后):

從結(jié)果中可以看出:

 ?、賏ddEventListener()第三個(gè)參數(shù)的作用正如上面所說(shuō);

 ?、谕ㄟ^(guò)addEventListener()方法給同一對(duì)象注冊(cè)多個(gè)同類(lèi)型的事件,并不會(huì)發(fā)生忽略或覆蓋,而是會(huì)按順序依次執(zhí)行;

相對(duì)addEventListener()的是removeEventListener()方法,它同樣有三個(gè)參數(shù),前兩個(gè)參數(shù)自然跟addEventListener()的意義一樣,而第三個(gè)參數(shù)也只需跟相應(yīng)的addEventListener()的第三個(gè)參數(shù)保持一致即可,同樣可以省略,默認(rèn)值為false。它表示從對(duì)象中刪除某個(gè)事件處理函數(shù)。實(shí)例:

div1.addEventListener('click', div1BubbleFun, false);
div1.removeEventListener('click', div1BubbleFun, false);
function div1BubbleFun(){
 console.log('div1-bubble');
}

4.attachEvent()

  但是,IE8以及其之前版本的瀏覽器并不支持addEventListener()和removeEventListener()。相應(yīng)的,IE定義了類(lèi)似的方法attachEvent()和detachEvent()。因?yàn)镮E8以及其之前版本瀏覽器也不支持事件捕獲,所以attachEvent()并不能注冊(cè)捕獲過(guò)程中的事件處理函數(shù),因此attachEvent()和detachEvent()要求只有兩個(gè)參數(shù):事件類(lèi)型和事件處理函數(shù)。而且,它們的第一個(gè)參數(shù)使用了帶“on”前綴的事件處理程序?qū)傩悦?。?shí)例:

var div1 = document.getElementById('div1');
div1.attachEvent('onclick', div1BubbleFun);
function div1BubbleFun(){
  console.log('div1-bubble');
}

  相應(yīng)的,從對(duì)象上刪除事件處理程序函數(shù)使用detachEvent()。例如:

div1.detachEvent('onclick', div1BubbleFun);

  到此為止,我們已經(jīng)說(shuō)了瀏覽器中事件傳播機(jī)制以及各種注冊(cè)事件處理程序的方法。下面我們就再說(shuō)說(shuō)事件處理程序調(diào)用時(shí)的一些問(wèn)題吧!

二.事件處理程序的調(diào)用

1.事件處理程序的參數(shù):正如前面所說(shuō),通常事件對(duì)象作為參數(shù)傳遞給事件處理函數(shù),但I(xiàn)E8以及其之前版本的瀏覽器中全局變量event才是事件對(duì)象。所以,我們?cè)趯?xiě)相關(guān)代碼時(shí)應(yīng)該注意兼容性問(wèn)題。實(shí)例(給頁(yè)面上id為div1的元素添加點(diǎn)擊事件,當(dāng)點(diǎn)擊該元素時(shí)在控制臺(tái)輸出事件類(lèi)型和被點(diǎn)擊元素本身):

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow: hidden;}
 </style>
</head>
<body>
 <div id="div1">div1</div>
 <script type="text/javascript">
 var div1 = document.getElementById('div1');
 if(div1.addEventListener){
 div1.addEventListener('click', div1Fun, false);
 }else if(div1.attachEvent){
 div1.attachEvent('onclick', div1Fun);
 }
 function div1Fun(event){
 event = event || window.event;
 var target = event.target || event.srcElement;
 console.log(event.type);
 console.log(target);
 }
 </script>
</body>
</html>

2.事件處理程序的運(yùn)行環(huán)境:關(guān)于事件處理程序的運(yùn)行環(huán)境,也就是在事件處理程序中調(diào)用上下文(this值)的指向問(wèn)題,可以看下面四個(gè)實(shí)例。

實(shí)例一:

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow: hidden;}
 </style>
</head>
<body>
 <div id="div1" onclick="console.log('html:'); console.log(this);">div1</div>
 <script type="text/javascript">
 </script>
</body>
</html>

  結(jié)果一:

  從結(jié)果可以看出:

   ?、俚谝环N方法事件處理程序中this指向這個(gè)元素本身;

實(shí)例二:

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow: hidden;}
 </style>
</head>
<body>
 <div id="div1" onclick="console.log('html:'); console.log(this);">div1</div>
 <script type="text/javascript">
 var div1 = document.getElementById('div1');
 div1.onclick = function(){
 console.log('div1.onclick:');
 console.log(this);
 };
 </script>
</body>
</html>

  結(jié)果二:

  從結(jié)果可以看出:

   ?、俚诙N方法事件處理程序中this也指向這個(gè)元素本身;

   ?、诖嬖诘诙N方法時(shí),它會(huì)覆蓋第一種方法注冊(cè)的事件處理程序;

實(shí)例三:

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow: hidden;}
 </style>
</head>
<body>
 <div id="div1" onclick="console.log('html:'); console.log(this);">div1</div>
 <script type="text/javascript">
 var div1 = document.getElementById('div1');
 div1.onclick = function(){
 console.log('div1.onclick:');
 console.log(this);
 };
 div1.addEventListener('click', function(){
 console.log('div1.addEventListener:');
 console.log(this);
 }, false);
 </script>
</body>
</html>

  結(jié)果三:

  從結(jié)果可以看出:

    ①第三種方法事件處理程序中this也指向這個(gè)元素本身;

   ?、诘谌N方法并不會(huì)覆蓋第一種或第二種方法注冊(cè)的事件處理程序;

實(shí)例四:

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow: hidden;}
 </style>
</head>
<body>
 <div id="div1" onclick="console.log('html:'); console.log(this);">div1</div>
 <script type="text/javascript">
 var div1 = document.getElementById('div1');
 div1.onclick = function(){
 console.log('div1.onclick:');
 console.log(this);
 };
 div1.attachEvent('onclick', function(){
 console.log('div1.attachEvent:');
 console.log(this === window);
 });
 
 </script>
</body>
</html>

  結(jié)果四:

  從結(jié)果可以看出:

   ?、俚谒姆N方法事件處理程序中this指向全局對(duì)象Window;

    ②第四種方法也不會(huì)覆蓋第一種或第二種方法注冊(cè)的事件處理程序;

3.事件處理程序的調(diào)用順序:多個(gè)事件處理程序調(diào)用規(guī)則如下:

 ?、偻ㄟ^(guò)HTML屬性注冊(cè)的處理程序和通過(guò)設(shè)置對(duì)象屬性的處理程序一直優(yōu)先調(diào)用;

 ?、谑褂胊ddEventListener()注冊(cè)的處理程序按照它們的注冊(cè)順序依次調(diào)用;

 ?、凼褂胊ttachEvent()注冊(cè)的處理程序可能按照任何順序調(diào)用,所以代碼不應(yīng)該依賴(lài)于調(diào)用順序;

4.事件取消:

①取消事件的瀏覽器默認(rèn)操作(比如點(diǎn)擊超鏈接元素會(huì)自動(dòng)發(fā)生頁(yè)面跳轉(zhuǎn)的默認(rèn)操作):如果使用前兩種方法注冊(cè)事件處理程序,可以在處理程序中添加返回值false來(lái)取消事件的瀏覽器默認(rèn)操作。在支持addEventListener()的瀏覽器中,也可以通過(guò)調(diào)用事件對(duì)象的preventDefault()方法取消事件的默認(rèn)操作。至于IE8及其之前的瀏覽器可以通過(guò)設(shè)置事件對(duì)象的returnValue屬性為false來(lái)取消事件的默認(rèn)操作。參考代碼:

function cancelHandler(event){
 var event = event || window.event;
 if(event.preventDefault){
 event.preventDefault();
 }
 if(event.returnValue){
 event.returnValue = false;
 }
 return false;
}

②取消事件傳播:在支持addEventListener()的瀏覽器中,可以調(diào)用事件對(duì)象的一個(gè)stopPropagation()方法阻止事件的繼續(xù)傳播,它能工作在事件傳播期間的任何階段(捕獲期階段、事件目標(biāo)本身、冒泡階段);但是在IE8以及其之前版本的瀏覽器中并不支持stopPropagation()方法,而且這些瀏覽器也不支持事件傳播的捕獲階段,相應(yīng)的,IE事件對(duì)象有一個(gè)cancelBubble屬性,設(shè)置這個(gè)屬性為true能阻止事件進(jìn)一步傳播(即阻止其冒泡)。參考代碼(阻止發(fā)生在div3區(qū)域的點(diǎn)擊事件冒泡到div2和div1):

<!DOCTYPE HTML>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
 <title>test</title>
 <style type="text/css">
 #div1{width: 300px; height: 300px; background: red; overflow:hidden;}
 #div2{margin:50px auto; width: 200px; height: 200px; background: green; overflow:hidden;}
 #div3{margin:50px auto; width: 100px; height: 100px; background: blue;}
 </style>
</head>
<body>
 <div id="div1">div1
 <div id="div2">div2
 <div id="div3">div3
 </div>
 </div>
 </div>
 <script type="text/javascript">
 var div1 = document.getElementById('div1');
 var div2 = document.getElementById('div2');
 var div3 = document.getElementById('div3');
    div1.onclick = function(){
 console.log('div1');
    };
    div2.onclick = function(){
 console.log('div2');
    };
    div3.onclick = function(event){
 stopEventPropagation(event);
 console.log('div3');
    };
 
 function stopEventPropagation(event){
 var event = event || window.event;
 if(event.stopPropagation){
 event.stopPropagation();
 }else{
 event.cancelBubble = true;
 }
 }
 </script>
</body>
</html>

以上就是javascript事件處理的全部介紹,當(dāng)然,關(guān)于事件冒泡還是有可利用之處的,這也就是我們常說(shuō)的事件代理或者事件委托,對(duì)于這方面知識(shí)以后會(huì)陸續(xù)更新。

相關(guān)文章

最新評(píng)論