整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          JavaScript事件流詳解

          JavaScript事件流詳解

          解Javascript事件流

          事件流

          事件流出現(xiàn)的歷史背景

          當(dāng)瀏覽器發(fā)展到第四代時(shí)(IE4 及 Netscape Communicator 4),瀏覽器開發(fā)團(tuán)隊(duì)遇到了一個(gè)很有意思 的問題:頁面的哪一部分會(huì)擁有某個(gè)特定的事件?要明白這個(gè)問題問的是什么,可以想象畫在一張紙上 的一組同心圓。如果你把手指放在圓心上,那么你的手指指向的不是一個(gè)圓,而是紙上的所有圓。兩家 公司的瀏覽器開發(fā)團(tuán)隊(duì)在看待瀏覽器事件方面還是一致的。如果你單擊了某個(gè)按鈕,他們都認(rèn)為單擊事 件不僅僅發(fā)生在按鈕上。換句話說,在單擊按鈕的同時(shí),你也單擊了按鈕的容器元素,甚至也單擊了整 個(gè)頁面。

          事件流描述的是從頁面中接收事件的順序。

          但有意思的是,IE 和 Netscape 開發(fā)團(tuán)隊(duì)居然提出了差 不多是完全相反的事件流的概念。IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事件捕獲流。

          事件冒泡

          IE的事件流叫做時(shí)間冒泡,即事件開始時(shí)由文檔中最內(nèi)層的元素接收,然后逐級(jí)往上傳播。

          <!DOCTYPE html>
          <html>
           <head>
           <title>Event Bubbling Example</title>
           </head>
           <body>
           <div id="myDiv">Click Me</div>
           </body>
          </html>
          

          如果你單擊了頁面中的<div>元素,那么這個(gè) click 事件會(huì)按照如下順序傳播:

          div->body->html->document
          

          也就是說,click 事件首先在<div>元素上發(fā)生,而這個(gè)元素就是我們單擊的元素。然后,click 事件沿 DOM 樹向上傳播,在每一級(jí)節(jié)點(diǎn)上都會(huì)發(fā)生,直至傳播到 document 對(duì)象。圖 13-1 展示了事件 冒泡的過程。

          IE事件流

          所有現(xiàn)代瀏覽器都支持事件冒泡,但在具體實(shí)現(xiàn)上還是有一些差別。IE5.5 及更早版本中的事件冒 泡會(huì)跳過<html>元素(從<body>直接跳到 document)。IE9、Firefox、Chrome 和 Safari 則將事件一直 冒泡到 window 對(duì)象。

          事件捕獲

          Netscape Communicator 團(tuán)隊(duì)提出的另一種事件流叫做事件捕獲(event capturing)。事件捕獲的思想是不太具體的節(jié)點(diǎn)應(yīng)該更早接收到事件,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件。事件捕獲的用意在于在 事件到達(dá)預(yù)定目標(biāo)之前捕獲它。如果仍以前面的 HTML 頁面作為演示事件捕獲的例子,那么單擊<div> 元素就會(huì)以下列順序觸發(fā) click 事件。

          document->html->body->div
          

          在事件捕獲過程中,document 對(duì)象首先接收到 click 事件,然后事件沿 DOM 樹依次向下,一直傳播到事件的實(shí)際目標(biāo),即<div>元素 。

          事件捕獲

          雖然事件捕獲是 Netscape Communicator 唯一支持的事件流模型,但 IE9、Safari、Chrome、Opera 和 Firefox 目前也都支持這種事件流模型。盡管“DOM2 級(jí)事件”規(guī)范要求事件應(yīng)該從 document 對(duì)象開始傳播,但這些瀏覽器都是從 window 對(duì)象開始捕獲事件的。

          由于老版本的瀏覽器不支持,因此很少有人使用事件捕獲。

          DOM事件流

          “DOM2級(jí)事件”規(guī)定的事件流包括三個(gè)階段:事件捕獲階段處于目標(biāo)階段事件冒泡階段。首 先發(fā)生的是事件捕獲,為截獲事件提供了機(jī)會(huì)。然后是實(shí)際的目標(biāo)接收到事件。最后一個(gè)階段是冒泡階段,可以在這個(gè)階段對(duì)事件做出響應(yīng)。以前面簡單的 HTML 頁面為例,單擊<div>元素會(huì)按照如下圖所示順序觸發(fā)事件。

          DOM事件流

          DOM 事件流中,實(shí)際的目標(biāo)(<div>元素)在捕獲階段不會(huì)接收到事件。這意味著在捕獲階段, 事件從 document 到<html>再到<body>后就停止了。下一個(gè)階段是“處于目標(biāo)”階段,于是事件在<div> 上發(fā)生,并在事件處理(后面將會(huì)討論這個(gè)概念)中被看成冒泡階段的一部分。然后,冒泡階段發(fā)生, 事件又傳播回文檔。

          多數(shù)支持 DOM 事件流的瀏覽器都實(shí)現(xiàn)了一種特定的行為;即使“DOM2 級(jí)事件”規(guī)范明確要求捕 獲階段不會(huì)涉及事件目標(biāo),但 IE9、Safari、Chrome、Firefox 和 Opera 9.5 及更高版本都會(huì)在捕獲階段觸 發(fā)事件對(duì)象上的事件。結(jié)果,就是有兩個(gè)機(jī)會(huì)在目標(biāo)對(duì)象上面操作事件。

          之后我們講解事件處理順序

          文章參考《JavaScript高級(jí)程序設(shè)計(jì)》(第三版)。

          件流:

          事件冒泡

          取消冒泡:oEvent.cancelBubble=true

          <html>
          <head>
          <meta charset="utf-8">
          <title>無標(biāo)題文檔</title>
          <style>
          #div1 {width:400px; height:300px; background:#CCC; display:none;}
          </style>
          <script>
          window.onload=function ()
          {
              var oBtn=document.getElementById('btn1');
              var oDiv=document.getElementById('div1');
          
              oBtn.onclick=function (ev)
              {
              var oEvent=ev||event;
          
              oDiv.style.display='block';
              //alert('按鈕被點(diǎn)擊了');
          
              oEvent.cancelBubble=true; //取消事件冒泡,是解決許多問題的方法和手段
              };
          
              document.onclick=function ()
              {
              oDiv.style.display='none';
              //alert('document被點(diǎn)擊了');
              };
          };
          </script>
          </head>
          <body>
          <input id="btn1" type="button" value="顯示" />
          <div id="div1">
          </div>
          </body>
          </html>

          冒泡型事件:

          <html>
          <head>
          <title>冒泡型事件</title>
          <script language="javascript">
          function add(sText){
          var oDiv=document.getElementById("display");
          oDiv.innerHTML +=sText; //輸出點(diǎn)擊順序
          }
          </script>
          </head>
          <body onclick="add('body<br>');">
          <div onclick="add('div<br>');">
          <p onclick="add('p<br>');">Click Me</p>
          </div>
          <div id="display"></div>
          </body>
          </html>

          執(zhí)行順序:p對(duì)象 -> div對(duì)象 -> body對(duì)象

          冒泡型事件執(zhí)行順序::由內(nèi)到外(p -> div -> body -> document)

          注意: DOM 0級(jí)只有冒泡, 沒有捕獲

          捕獲型事件

          相對(duì)于IE使用冒泡型事件, Netscape使用了另一種稱為捕獲型事件(eventcapturing)的解決方案;

          addEventListener(事件名稱,函數(shù), bCapture)

          removeEventListener(事件名稱, 函數(shù), bCapture)

          事件監(jiān)聽函數(shù)第三個(gè)參數(shù)bCapture確定是冒泡型還是捕獲型事件(true:捕獲 false:冒泡,默認(rèn)值false)

          <!DOCTYPE html>
          <html>
          <head>
          <style>
          div {
          background-color: coral;
          border: 1px solid;
          padding: 50px;
          }
          </style>
          </head>
          <body>
          <div id="myDiv2">
          <p id="myP2">點(diǎn)擊該段落, 我是捕獲</p>
          </div>
          <script>
          document.getElementById("myP2").addEventListener("click", function() {
          alert("你點(diǎn)擊了 P 元素!");
          }, true);
          document.getElementById("myDiv2").addEventListener("click", function() {
          alert("你點(diǎn)擊了 DIV 元素!");
          }, true);
          </script>
          </body>
          </html>

          執(zhí)行順序: div對(duì)象 -> p對(duì)象

          捕獲型事件執(zhí)行順序:由外到內(nèi)(如:document -> body -> div -> p)

          冒泡型:事件從內(nèi)部往外部依次執(zhí)行。

          捕捉型:事件從外部往內(nèi)部依次執(zhí)行。

          事件監(jiān)聽

          通用監(jiān)聽方法:

          1.直接在HTML標(biāo)簽中分配事件處理函數(shù):

          <script language="javascript">
          function add(sText){
          var oDiv=document.getElementById("display");
          oDiv.innerHTML +=sText; //輸出點(diǎn)擊順序
          }
          </script>
          </head>
          <body onclick="add('body<br>');">
          <div onclick="add('div<br>');">
          <p onclick="add('p<br>');">Click Me</p>
          </div>
          <div id="display"></div>
          </body>

          2.結(jié)構(gòu)與行為的分離:

          <html>
          <head>
          <title>監(jiān)聽函數(shù)</title>
          <script language="javascript">
          window.onload=function(){
          var oP=document.getElementById("myP"); //找到對(duì)象
          oP.onclick=function(){ //設(shè)置事件監(jiān)聽函數(shù)
          alert('我被點(diǎn)擊了');
          }
          }
          </script>
          </head>
          <body>
          <div>
          <p id="myP">Click Me</p>
          </div>
          </body>
          </html>

          事件監(jiān)聽的作用:

          <!DOCTYPE HTML>
          <html>
          <head>
          <meta charset="utf-8">
          <title>無標(biāo)題文檔</title>
          <script>
          window.onload=function ()
          {
          alert('a');
          };
          window.onload=function ()
          {
          alert('b');
          };
          </script>
          </head>
          <body>
          </body>
          </html>

          以上程序只彈出alert('b');

          理解:對(duì)同一對(duì)象執(zhí)行兩次事件(同一事件類型)處理函數(shù)時(shí),往往只能只執(zhí)行后一個(gè)

          因此如果要讓腳本在本瀏覽器中正常運(yùn)行的話,就必須使用瀏覽器所支持的事件監(jiān)聽器

          IE中的監(jiān)聽方法:

          attachEvent(事件名稱, 函數(shù)), 綁定事件處理函數(shù) attach: 貼上, 附著

          detachEvent(事件名稱, 函數(shù)), 解除綁定 detach: 分離, 拆開

          注意:IE只支持冒泡型事件監(jiān)聽, 沒有第三個(gè)參數(shù), 事件名稱前要加"on";

          <html>
          <head>
          <title>多個(gè)監(jiān)聽函數(shù)</title>
          <script language="javascript">
          function fnClick1(){
          alert("我被fnClick1點(diǎn)擊了");
          }
          function fnClick2(){
          alert("我被fnClick2點(diǎn)擊了");
          //oP.detachEvent("onclick",fnClick1); //刪除監(jiān)聽函數(shù)1
          }
          var oP;
          window.onload=function(){
          oP=document.getElementById("myP"); //找到對(duì)象
          oP.attachEvent("onclick",fnClick1); //添加監(jiān)聽函數(shù)1
          oP.attachEvent("onclick",fnClick2); //添加監(jiān)聽函數(shù)2
          }
          </script>
          </head>
          <body>
          <div>
          <p id="myP">Click Me</p>
          </div>
          </body>
          </html>

          標(biāo)準(zhǔn)DOM的事件監(jiān)聽:

          addEventListener(事件名稱,函數(shù), 捕獲)

          element.addEventListener(event, function, useCapture)

          removeEventListener(事件名稱, 函數(shù), 捕獲)

          element.removeEventListener(event, function, useCapture)

          bCapture 是用于冒泡階段還是捕獲階段(true:捕獲 false:冒泡,默認(rèn)值false)

          注意:IE9版本已支持

          <html>
          <head>
          <title>標(biāo)準(zhǔn)DOM的事件監(jiān)聽</title>
          <script language="javascript">
          function fnClick1(){
          alert("我被fnClick1點(diǎn)擊了");
          //oP.removeEventListener("click",fnClick2,false); //刪除監(jiān)聽函數(shù)2
          }
          function fnClick2(){
          alert("我被fnClick2點(diǎn)擊了");
          }
          var oP;
          window.onload=function(){
          oP=document.getElementById("myP"); //找到對(duì)象
          oP.addEventListener("click",fnClick1,false); //添加監(jiān)聽函數(shù)1
          oP.addEventListener("click",fnClick2,false); //添加監(jiān)聽函數(shù)2
          }
          </script>
          </head>
          <body>
          <div>
          <p id="myP">Click Me</p>
          </div>
          </body>
          </html>

          編寫兼容性事件監(jiān)聽函數(shù)

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

          實(shí)例:

          avascript事件基礎(chǔ)-事件流

          #JavaScript#

          事件就是多個(gè)節(jié)點(diǎn)對(duì)象對(duì)同一個(gè)事件進(jìn)行響應(yīng)的先后順序。

          1.冒泡型

          事件從上向下進(jìn)行響應(yīng),稱冒泡

          實(shí)例1.含五層嵌套的Div標(biāo)簽,當(dāng)點(diǎn)擊Div事件時(shí),對(duì)象邊框邊紅色,并抓取標(biāo)簽名。

          代碼演示

          瀏覽結(jié)果

          點(diǎn)擊click事件,從內(nèi)到外一次響應(yīng)。

          完整代碼


          主站蜘蛛池模板: 亚洲高清一区二区三区电影| 日韩一区二区在线播放| 欲色aV无码一区二区人妻| 在线播放国产一区二区三区 | 亚洲午夜一区二区三区| 韩国资源视频一区二区三区| 污污内射在线观看一区二区少妇 | 无码精品尤物一区二区三区| 高清一区高清二区视频| 日韩成人一区ftp在线播放| 亚洲av一综合av一区| 亚洲一区二区三区无码影院| 海角国精产品一区一区三区糖心| 日韩一区二区在线观看视频| 日韩人妻无码一区二区三区久久99 | AA区一区二区三无码精片| 精品aⅴ一区二区三区| 亚洲日本一区二区一本一道| 婷婷亚洲综合一区二区| 午夜视频一区二区三区| 无码人妻一区二区三区av| 在线精品视频一区二区| 韩国福利视频一区二区| 秋霞日韩一区二区三区在线观看| 精品深夜AV无码一区二区老年| 久久er99热精品一区二区| 亚洲伦理一区二区| 97久久精品一区二区三区| 日本免费一区二区三区| 亚洲精品一区二区三区四区乱码| 麻豆高清免费国产一区| 亚洲av永久无码一区二区三区| 中文字幕一区精品| 久久精品道一区二区三区| 国产精品第一区揄拍| 精品国产免费观看一区| 国产精华液一区二区区别大吗| 久久一区二区明星换脸| 国产精品无码一区二区三区不卡| 国产天堂在线一区二区三区| 一区二区三区影院|