站長資訊網(wǎng)
        最全最豐富的資訊網(wǎng)站

        JavaScript事件之事件冒泡與時間捕獲(總結(jié)分享)

        本篇文章給大家?guī)砹薐avaScript中關(guān)于事件的基礎(chǔ)知識詳解,其中包括了事件冒泡和時間捕獲,希望對大家有幫助。

        JavaScript事件之事件冒泡與時間捕獲(總結(jié)分享)

        一、事件冒泡與事件捕獲

        當(dāng)我們在Web頁面單擊某一個元素的時候,比如某個p元素。仔細(xì)想想,我們單擊的不僅僅是這一個p元素,一同被單擊的還有以該p為圓心的同心圓元素,比如元素的父,外層body、body的父元素html還有外層的document。事件在這些嵌套的元素之間的傳播稱為事件流。

        • 1、事件冒泡
        • 2、事件捕獲

        1、事件冒泡

        IE的事件流稱為事件冒泡,事件從最具體的元素開始,逐級向上傳播。我們使用DOM0添加的事件處理程序就是在事件冒泡階段被處理的。例如:

        <html>   <head>     <script type="text/javascript">        window.onload = bubblingHandle;      function bubblingHandle() {           //內(nèi)層p處理程序           document.getElementById("inner").onmousedown     = function() {               alert("inner p");           }          //外層p處理程序           document.getElementById("outer").onmousedown = function() {               alert("outerp");           }            document.onmousedown = function() {               alert("document");           }       }        -->    </script>   </head>   <body>     <p id="outer" style="background-color:black; padding: 15px;">         <p id="inner" style="background-color:white; padding: 5px;"></p>     </p>   </body></html>

        當(dāng)點擊內(nèi)層的白色p時,會依次顯示:

        inner p outer p document

        事件捕獲

        網(wǎng)景提出的事件流稱為事件捕獲,其與IE幾乎相反。事件首先由最不具體的元素接收,然后逐級向具體節(jié)點傳播。

        二、DOM0級事件處理

        事件,由WEB頁面中發(fā)生的一些特定行為觸發(fā)。比如在某個頁面元素上按下鼠標(biāo)左鍵,按下鍵盤某個按鍵,某對象獲得或丟失焦點時均會觸發(fā)對應(yīng)的事件。JavaScript和HTML的交互就是通過事件來實現(xiàn)的。我們使用事件偵聽器對事件進行“注冊”,事件發(fā)生時便執(zhí)行相應(yīng)的代碼。

        DOM0級事件處理程序以其簡單、跨瀏覽器支持的特點,至今仍為所有瀏覽器支持。

        • 通過DOM0級方法指定事件處理程序
        • 事件處理程序中的this
        • 通過DOM0級方法刪除事件處理程序

        通過DOM0級方法指定事件處理程序

        通過DOM0級方法指定事件處理程序方法很簡單,首先取得一個要操作元素的引用,然后接將一個函數(shù)賦值給該元素的對應(yīng)事件處理程序?qū)傩?/code>。(每個元素包括window和document都擁有自己的事件處理程序?qū)傩?/code>。)注意,這種方法添加的事件處理程序?qū)⒃谑录鞯拿芭蓦A段被處理。

        有關(guān)事件處理程序?qū)傩裕幸韵聨c需要說明:

        1、事件處理程序?qū)傩匀啃懀浴眔n”開頭,后面跟事件類型:

        onclick  //單擊鼠標(biāo) onload  //圖像或頁面載入完成 onmouseover  //將鼠標(biāo)移動到某元素上面 onmousemove  //移動鼠標(biāo) onfocus  //對象獲得焦點

        2、每個元素如img、a、input、form包括window和document都擁有自己的事件處理程序?qū)傩浴H纾?/p>

        document.getElementById("btn1").onclick  //btn1上單擊鼠標(biāo) document.getElementById("img1").onmouseover  //鼠標(biāo)移動到img1 document.getElementById("img1").onmerror  //img1圖像無法載入

        接下來,給事件處理程序?qū)傩再x值即可完成事件處理程序方法的指定。例如,當(dāng)鼠標(biāo)移動到”img1”上時,彈出對話框”This is a nice pic!”:

        var pic1 = document.getElementById("img1"); pic1.onmouseover = function() {     alert("This is a nice pic!"); };

        特別注意:如果以上代碼處于文檔的底部,在頁面剛剛加載時,我們將鼠標(biāo)移動到img1上面。有可能由于代碼尚未執(zhí)行,不會彈出我們設(shè)定的對話框!如今,這個延遲已經(jīng)十分短暫。

        事件處理程序中的this

        通過DOM0級方法指定的事件處理程序,屬于元素方法。因此,我們在事件處理程序中的this引用的是該元素!通過以下例子來說明:

        <input id="btn1" type="button" value="Click Me" /> ...//省略 <script type="text/javascript">   <!--   var btn1 = document.getElementById("btn1");   btn1.onclick = function() {       alert(this.id + "n" + this.type + "n" + this.value);   };   --> </script>

        通過DOM0級方法刪除事件處理程序

        要刪除事件處理程序,只需要將對應(yīng)的事件處理程序?qū)傩栽O(shè)置為null即可:

        pic1.onmouseover = null;

        三、DOM2級事件處理

        1、addEventListener與removeEventListener

        目前,幾乎所有的瀏覽器都支持DOM0事件模型,但鼓勵開發(fā)人員使用新的DOM2模型。DOM2模型與DOM0有兩個顯著區(qū)別:

        • 1、DOM2不依賴事件處理程序?qū)傩?/li>
        • 2、可以同時對對象的同一事件注冊多個處理程序,它們按照注冊順序依次執(zhí)行。

        DOM2定義了2個方法:

        addEventListener()  //指定事件處理程序 removeEventListener()  //刪除事件處理程序

        所有DOM節(jié)點有包含這兩個方法,這兩個方法用法如下,它們都接收3個參數(shù),第1個為要處理事件名(不含on),第2個事件處理函數(shù),第3個布爾變量:

        例如我們?yōu)榘粹obtn1的單擊事件添加2個事件處理程序,事件處理程序在事件冒泡階段被處理:

        <input id="btn1" type="button" value="Click Me" /> ... <script type="text/javascript">   <!--   var btn1 = document.getElementById("btn1");   var handle1 = function() {       alert("handle1!");   }   var handle2 = function() {       alert("handle2!");   }   btn1.addEventListener("click", handle1, false);   btn1.addEventListener("click", handle2, false);   --> </script>

        當(dāng)單擊btn1按鈕時,會依次彈出對話框:

        handle1! handle2!

        我們可以用removeEventListener()方法來刪除我們剛才指定的事件處理程序,注意參數(shù)要保持一致:

        btn1.removeEventListener("click", handle2, false);

        此時單擊btn1按鈕,只會顯示handle1!。

        要特別注意的是,如果我們使用匿名函數(shù)指定事件處理程序,便無法使用removeEventListener()方法刪除事件處理程序:

         btn1.addEventListener("click", function(){      alert("click!");  }, false);   btn1.removeEventListener("click", function(){      alert("click!");  }, false);  //無法取消!

        這樣是無法取消以上指定的事件處理程序的!因為上面addEventListener和removeEventListener中的2個事件處理函數(shù)雖然代碼相同,實質(zhì)上是2個不同的函數(shù)引用。

        另外,強調(diào)一點,以上兩個函數(shù)的第一個參數(shù)(要處理的事件名)是沒有on前綴的。這一點和IE不同,后面會說明。

        tips: IE9, Firefox, Safari, Chrome以及Opera均支持DOM2級事件處理程序。

        DOM2事件處理程序中的this

        DOM2事件處理程序和DOM0相同,它們的this都在其依附的元素作用域中運行。this的指代參考DOM0的示例。這里之所以要特別指出DOM2的this,是為了和IE事件處理程序進行區(qū)分。IE中事件處理程序this與事件指定方式有關(guān)。

        四、IE事件處理程序及跨瀏覽器支持

        attachEvent()與detachEvent()

        IE并沒有提供對W3C事件模型的支持,其實現(xiàn)了2個和DOM2模型類似的方法:

        attachEvent() detachEvent()

        這兩個方法只接收2個參數(shù):事件名稱以及事件處理函數(shù)。由于IE8及更早版本只支持事件冒泡,這兩個方法添加的事件處理程序會在事件冒泡階段被執(zhí)行。

        和DOM2不同的是:

        • 1、IE事件處理方法運行作用域為全局作用域,this指代window;
        • 2、第一個參數(shù)事件名以on為前綴;
        • 3、當(dāng)為同一對象的相同事件指定多個處理程序時,執(zhí)行順序和DOM2相反,IE中以添加它們的相反順序執(zhí)行。

        例如:

        <input id="btn1" type="button" value="Click Me" /> ... <script type="text/javascript">   <!--   var btn1 = document.getElementById("btn1");   var handle1 = function() {       alert("handle1!" + "n" + (this === window));   };   var handle2 = function() {       alert("handle2!"+ "n" + (this === window));   };   btn1.attachEvent("onclick", handle1);   btn1.attachEvent("onclick", handle2);   --> </script>

        執(zhí)行結(jié)果:

        handle2! true  handle1! true

        跨瀏覽器支持

        雖然可以使用屏蔽瀏覽器差異的JS庫,實際上,我們自己編寫一個跨瀏覽器兼容的事件處理代碼并不是一件困難的事情,同時更有利于我們對原生JavaScript的學(xué)習(xí)理解。我們使用一個習(xí)慣上稱為EventUtil的對象來進行跨瀏覽器事件處理:

        var EventUtil = {     addEventHandler : function(element, eventType,        handler) {         if(element.addEventListener){             element.addEventListener(eventType, handler, flase);         } else if(element.attachEvent) {             element.attachEvent("on" + eventType, handler);         } else {             element["on" + eventType] = handler;         }     },      removeEventHandler : function(element, eventType, handler) {         if(element.aremoveEventListener){             element.addEventListener(eventType, handler, flase);         } else if(element.detachEvent) {             element.attachEvent("on" + eventType, handler);         } else {             element["on" + eventType] = null;         }     } }

        為了保證事件處理代碼能夠在大多數(shù)瀏覽器中一致地運行,我們這里只關(guān)注冒泡階段。以上代碼使用瀏覽器能力檢測,首先檢測是否支持DOM2級方法addEventListener和removeEventListener,如果支持則使用該方法;如果不支持該方法,檢測是否是IE8級更早版本的attachEvent或detachEvent方法,若支持則使用該方法;如果對以上2種方法都不支持,則使用DOM0級方法。要注意,DOM0級對每個事件只能指定一個事件處理程序。

        以上對象使用示例如下:

        var btn1 = document.getElementById("btn1");var handle1 = function() {     alert("handle1!" + "n" + (this === window)); };var handle2 = function() {     alert("handle2!"+ "n" + (this === window)); }; EventUtil.addEventHandler(btn1, "click", handler1); EventUtil.addEventHandler(btn1, "click", handler2);  EventUtil.removeEventHandler(btn1, "click", handler2);

        五、事件對象

        在觸發(fā)某個事件時,會產(chǎn)生一個event對象。該對象中包含與事件有關(guān)的信息。例如觸發(fā)事件的元素、事件的類型、與特定事件相關(guān)的如鼠標(biāo)位置信息等。

        • 1、DOM事件對象
        • 2、IE事件對象與跨瀏覽器事件對象

        1、DOM事件對象

        不論使用DOM0級還是DOM2級方法指定事件處理程序,事件觸發(fā)時都會自動將一個event對象傳入事件處理程序,例如:

        var btn1 = document.getElementById("btn1");  btn1.onmouseover = function(evnt) {     alert(evnt.type); }var handle = function(evnt) {     alert(evnt.type); }; btn1.addEventListener("click", handle, false);

        以上是一個簡單的event對象的示例。event對象中的type屬性是一個只讀字符串屬性,其中包含著事件的類型。例如我們上例中的click和onmouseover。event對象中包含有大量的有關(guān)事件的屬性和方法(例如event.stopPropagation()方法可用于停止事件在捕獲或者冒泡階段的繼續(xù)傳播,preventDefault()方法會取消阻止事件的行)在此就不一一列舉了。其中常用的如下:

        屬性/方法 值類型 讀寫 描述
        currentTarget Element readonly 事件處理程序當(dāng)前正在處理的元素
        target Element readonly 事件的目標(biāo)
        type String readonly 觸發(fā)事件的類型
        preventDefault Function readonly 取消事件默認(rèn)行為,如鏈接的默認(rèn)行為就是被單擊時跳轉(zhuǎn)到href指定的url
        stopPropagation Function readonly 取消事件進一步冒泡或捕獲

        2、IE事件對象與跨瀏覽器事件對象

        IE事件對象

        在IE中,當(dāng)使用DOM0級指定事件處理程序時,event對象被認(rèn)為是window的一個屬性,例如獲取鼠標(biāo)點擊坐標(biāo)的代碼:

        var mouseLoc = function() {     var loc = "x: " + window.event.screenX + "n" +              "y: " + window.event.screenY;     alert(loc); };

        當(dāng)使用attachEvent()方法指定事件處理程序時,event對象會被作為參數(shù)傳入事件處理程序,我們將以上的代碼重寫:

        var mouseLoc = function(event) {     var loc = "x: " + event.screenX + "n" +              "y: " + event.screenY;     alert(loc); }; btn1.attachEvent("onclick",  mouseLoc);

        IE中event對象的相關(guān)屬性方法:

        屬性/方法 值類型 讀寫 描述
        cancelBubble Boolean read/write 默認(rèn)為false,置為true時取消事件冒泡(同DOM中stopPropagation)
        returnValue Boolean read/write 默認(rèn)為true,設(shè)為false取消事件默認(rèn)行為(同DOM中preventDefault)
        srcElement Element readonly 事件目標(biāo)
        type String readonly 事件類型

        跨瀏覽器事件對象

        解決跨瀏覽器問題的思路是一貫的,我們可以對瀏覽器進行能力檢測,這里我們對上面的EventUtil對象進行擴展,對我們學(xué)習(xí)原生JS,這是一個很漂亮的對象:

        var EventUtil = {     addEventHandler : function(element, eventType, handler) {         if(element.addEventListener){             element.addEventListener(eventType, handler, flase);         } else if(element.attachEvent) {             element.attachEvent("on" + eventType, handler);         } else {             element["on" + eventType] = handler;         }     },      removeEventHandler : function(element, eventType, handler) {         if(element.aremoveEventListener){             element.addEventListener(eventType, handler, flase);         } else if(element.detachEvent) {             element.attachEvent("on" + eventType, handler);         } else {             element["on" + eventType] = null;         }     },      getEvent: function (event) {         return event ? event : window.event;     },      getTarget: function (event) {         return event.target || event.srcElement;     },      preventDefault: function (event) {         if (event.preventDefault) {             event.preventDefault();         } else {             event.returnValue = false;         }     },      stopPropagation: function (event) {         if (event.stopPropagation) {             event.stopPropagation();         } else {             event.cancelBubbles = true;         }     },      getRelatedTarget: function (event) {         if (event.relatedTarger) {            return event.relatedTarget;         } else if (event.toElement) {            return event.toElement;         } else if (event.fromElement) {            return event.fromElement;         } else { return null; }     } }

        贊(0)
        分享到: 更多 (0)
        網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號
        主站蜘蛛池模板: 99精品欧美一区二区三区| 日本精品少妇一区二区三区| 国产情侣大量精品视频| 55夜色66夜色国产精品视频| 亚洲欧洲久久久精品| 国产精品亚洲αv天堂无码| 国产精品亚洲一区二区三区在线 | 国产精品久久99| 亚洲AV永久青草无码精品| 精品无码专区亚洲| 亚洲国产精品人久久| 99re8这里有精品热视频免费 | 亚洲国模精品一区| 精品一区二区三区高清免费观看 | 91国内揄拍国内精品对白不卡| 国产国拍亚洲精品mv在线观看 | 日韩精品久久久肉伦网站| 日本精品一区二区三区在线视频| 成人午夜精品亚洲日韩| 91精品国产福利在线观看| 精品999在线| www.久久精品| 99精品国产高清一区二区麻豆| 少妇人妻无码精品视频| 一本色道久久88—综合亚洲精品| 99精品视频3| 色婷婷在线精品国自产拍| 欧美在线精品一区二区三区| 国产综合免费精品久久久| 87国产私拍福利精品视频| 久久九九亚洲精品| 精品久久一区二区三区| 国产精品一二三区| 久久99国产精品久久久| 国产精品免费精品自在线观看| 91精品视频网站| 国产精品久久波多野结衣| 国产91精品在线| 成人精品在线视频| 久久99精品国产一区二区三区| 2018国产精华国产精品|