The NoteBook of EricKong

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

          事件就是用戶或者瀏覽器自身執(zhí)行的某種動(dòng)作。諸如click、load、和scroll等等,都是事件的名字。而響應(yīng)某個(gè)事件的函就叫做事件處理程序(或事件偵聽器)。事件處理程序的名字都是以”on“開頭,因此ckick事件的事件處理程序就是onclick,load的事件處理程序就是onload。

          頁(yè)面中添加事件的有幾種方式

          1. 直接將代碼寫在HTMl上

            <div onclick="alert('Hello World');">Nowamagic</div>

            代碼少的還勉強(qiáng)可以,代碼多的話就哭了寫頁(yè)面的哥們了。

          2. 定義一個(gè)函數(shù),分配給html元素

            <script type="text/javascript"> function clk(){} </script> //..... <div onclick="clk()">Div2 Element</div>

            這樣做雖然能減少html代碼上的js量,但是這樣子做有幾個(gè)缺點(diǎn):用戶可能在HTMl代碼已經(jīng)出現(xiàn)在頁(yè)面上,但是js事件函數(shù)可能還沒加載進(jìn)來的情況下就點(diǎn)擊了事件對(duì)象元素,從而導(dǎo)致錯(cuò)誤;還有就是HTML與javascript代碼還是未分離完全,如果要修改就要改HTML代碼和javascript代碼兩處

          3. HTML與javascript代碼完全分離

            document.getElementById('myButton').onclick = function(){     alert('Hello!'); } <div id="myButton">點(diǎn)擊按鈕/div>

            它只需要HTML元素提供一個(gè)id屬性(或其它能獲取該元素對(duì)象的方式),就可以實(shí)現(xiàn)事件的注冊(cè)。真正做到HTML與javascript代碼完全分離,結(jié)構(gòu)與行為完全分離的事件處理方法。

          如何監(jiān)聽事件

          DOM Leavl 0

          DOM Leavl 0是最早的事件處理形式,它既可以直接寫在HTMl上,也可以把一個(gè)函數(shù)分配給一個(gè)事件處理程序。然而,這種方式給一個(gè)元素的同一事件只允許一個(gè)處理器。因此,我們還要繼續(xù)完善。

          W3C DOM Leavl 2 – 事件監(jiān)聽器

          通過W3C DEMO Leavl 2事件處理,我們不會(huì)直接把一個(gè)函數(shù)分配給一個(gè)事件處理程序;相反,我們將新函數(shù)添加一個(gè)事件監(jiān)聽器:

          var el = document.getElementById('myButton') el.addEventListener( 'click', function(){     alert('Hello!'); }, false)
          targetElement.addEventlistener(typeOfEvent,listenerFunction,useCapture);
          W3C DOM Leaval 2通用語(yǔ)法

          盡管這個(gè)方法看起來比之前那個(gè)方法復(fù)雜了一點(diǎn),但是那些額外的代碼還是有必要打出來的。對(duì)于DOM級(jí)別2的事件最大的好處就是一個(gè)事件可以注冊(cè)許多處理器。

          addEventlistener的頭兩個(gè)參數(shù)是目標(biāo)對(duì)象和事件,不僅如此,函數(shù)最后一個(gè)參數(shù),可以指定處理器是在捕獲階段還是冒泡階段被觸發(fā)(通過設(shè)置”addEventListener()”函數(shù)的第三個(gè)參數(shù)來指定 – true表示在捕獲階段,false表示在冒泡階段)

          接下來將針對(duì)W3C DOM Leavl 2事件進(jìn)行討論。

          事件在文檔中被傳遞的兩種模型

          W3C DOM Leavl 2事件流包括三個(gè)階段:事件捕獲階段、處于目標(biāo)簡(jiǎn)短和事件冒泡階段。

          首先我們了解下事件冒泡和事件捕獲。

          事件冒泡

          在頁(yè)面上有多個(gè)事件,也可以多個(gè)元素響應(yīng)同一個(gè)事件。假設(shè)網(wǎng)頁(yè)上有兩個(gè)元素,其中一個(gè)元素嵌套在另一個(gè)元素中,并且都被綁定了 click 事件,同時(shí) body 也綁定了 click 事件,如下:

          js代碼如下:

          window.onload = function(){ var oBubble = document.getElementById("oBubble"); var oBubble1 = document.getElementById("oBubble1"); var oBubble2 = document.getElementById("oBubble2"); oBubble.onclick = function(){ alert("Bubble") } oBubble1.onclick = function(){ alert("Bubble1") } oBubble2.onclick = function(){ alert("Bubble2") } }

          html代碼如下:

          <body id="oBubble">//點(diǎn)擊#oBubble彈出Bubble     <div id="oBubble1">//點(diǎn)擊#oBubble1先后彈出Bubble1、Bubble         <span id="oBubble2">oBubble</span>//點(diǎn)擊#oBubble2先后彈出Bubble2 、Bubble1、Bubble     </div> </body>

          事件順序:span→div→body,如下圖所示:

          JavaScript欲速則不達(dá)——基本處理事件詳解和阻止事件傳播
          事件冒泡實(shí)例圖例

          很明顯,每個(gè)元素都會(huì)按照(inside→outside)的冒泡型事件,所以事件冒泡會(huì)引起預(yù)料之外的效果。事件冒泡是IE-DOM處理事件對(duì)象的方法。

          事件捕獲

          事件捕獲和事件冒泡是剛好相反的兩個(gè)過程,事件捕獲是按照(outside→inside)的冒泡型事件開始觸發(fā)。因此拿以上冒泡例子,alert信息是跟事件冒泡完全相反的順序。

          一些注意事項(xiàng):

          1. W3C DOM Leavl 2標(biāo)準(zhǔn)的addEventListener方法執(zhí)行事件的順序是按照事件注冊(cè)的順序執(zhí)行的。而IE的attachEvent方法則相反–后注冊(cè)的事件先觖發(fā),先注冊(cè)的事件后觸發(fā)。
          2. W3C DOM Leavl 2標(biāo)準(zhǔn)的瀏覽器文本節(jié)點(diǎn)也會(huì)冒泡,而IE內(nèi)核的瀏覽器文本節(jié)點(diǎn)不會(huì)冒泡。
          3. W3C DOM Leavl 2瀏覽器事件對(duì)象與IE內(nèi)核的瀏覽器事件不同(具體請(qǐng)參閱)。
          4. DOM標(biāo)準(zhǔn)的瀏覽器事件卸載方式與IE內(nèi)核的事件卸載方式不同。

          接下來我們就來解決跨瀏覽器的事件處理的方案。

          跨瀏覽器的事件處理函數(shù)

          前面我們介紹了事件冒泡和事件捕獲兩種事件事件獲取方式,而W3C模型 是兩者中和。就是事件發(fā)生時(shí),先從頂層開始進(jìn)行事件捕獲,直到事件觸發(fā)到達(dá)了事件源元素。然后,再?gòu)氖录赐线M(jìn)行事件冒泡,直到到達(dá)document。

          利用W3C DOM Leavl 2事件監(jiān)聽器,就是 addEventListener函數(shù)。我們可以自己選擇綁定事件時(shí)采用事件捕獲還是事件冒泡,方法就是綁定事件時(shí)通過addEventListener函數(shù),上面我們介紹過它的三個(gè)參數(shù)了:如果第三個(gè)參數(shù)若是true,則表示采用事件捕獲,若是false,則表示采用事件冒泡。

          但是在一個(gè)支持W3C DOM的瀏覽器中,按照DOM Leavl 1綁定事件方式,采用的全都是事件冒泡方式。大多數(shù)時(shí)候,我們也是希望事件從內(nèi)部嵌套的的元素冒泡到外圍元素。

          解決方案

          以上我們介紹過 W3C DOM Leaval 2事件綁定中的addEventlistener,可以為元素添加多個(gè)事件,而且最后一個(gè)參數(shù)還支持事件冒泡或捕獲,IE6/7/8仍然沒有遵循標(biāo)準(zhǔn)而使用了自己專有的attachEvent,且不支持事件捕獲,所有事件都是發(fā)生在冒泡階段。

          所以創(chuàng)建一個(gè)可重用。實(shí)現(xiàn)了DOM Leavl 2事件處理的事件處理函數(shù),但是,它還是要跨瀏覽器。如下經(jīng)典代碼

          listenEvent函數(shù)代碼

          function listenEvent(eventTarget, eventType, evrntHandler) { if (eventTarget.addEventListener){         eventTarget.addEventListener(eventType, evrntHandler, true);//IE9等其他現(xiàn)代瀏覽器 } else if (eventTarget.attachEvent){         eventType = "on"+eventType;         eventTarget.attachEvent(eventType,evrntHandler) //IE6、7、8 } else {eventTarget["on" + eventType] = evrntHandler;}//IE5~ 個(gè)人覺得不寫也罷。 }

          listenEvent函數(shù)使用

          listenEventdocument,"click",processClick
          可重用的事件處理函數(shù)

          此處理函數(shù)接受3個(gè)函數(shù):目標(biāo)對(duì)象、事件(作為一個(gè)字符串),以及函數(shù)名稱。首先測(cè)試對(duì)象,看看它是否支持addEventListener(W3C DOM Leaval 2的事件監(jiān)聽方法),如果支持這個(gè)方法,就把事件映射到事件處理函數(shù)。回到代碼,因?yàn)镮E6、7、8不支持addEventListener,所以檢查是否支持attachEvent,記得前面加”on“,因?yàn)椴患?#8221;on“只是事件的名字,但是因?yàn)镮E6、7、8只支持向上冒泡,所以此方案中 addEventListener的第三個(gè)參數(shù)是false。最后為了兼容DOM leaval 0事件處理,還要加最后一行代碼。

          使用W3C DOM Leavl 2處理事件事件監(jiān)聽不會(huì)有覆蓋之前綁定事件的現(xiàn)象,每個(gè)綁定的事件都會(huì)被執(zhí)行,不過 attachEvent 為元素增加的一系列事件不是以添加它們順序執(zhí)行的,而是以相反的順序觸發(fā)。最重要的是,采用事件監(jiān)聽給對(duì)象綁定方法后,可以解除相應(yīng)的綁定。跟以上代碼類似,removeEventListener跟addEventListener對(duì)應(yīng),detachEvent跟eventType對(duì)應(yīng),得到如下解決方案:

          stopListening函數(shù)代碼

          function stopListening(eventTarget, eventType, evrntHandler) { if (eventTarget.removeEventListener){         eventTarget.removeEventListener(eventType, evrntHandler, true);//IE9等其他現(xiàn)代瀏覽器 } else if (eventTarget.attachEvent){         detachEvent = "on"+eventType;         eventTarget.detachEvent(eventType,evrntHandler) //IE6、7、8 } else {eventTarget["on" + eventType] = null;}//IE5~ }
          stopListeningdocument,"click",processClick
          可重用的事件處理函數(shù)

          在DOM標(biāo)準(zhǔn)的事件卸載方式中需要注意的是:事件捕獲的參數(shù)。如果你的事件是注冊(cè)在捕獲階段,則卸載事件時(shí),必須將其指定為捕獲階段(true),否則無法卸載;如果你的事件注冊(cè)在注冊(cè)在冒泡階段,則必須將其指定為冒泡階段(false),否則同樣無法卸載。

          現(xiàn)在,如果我們想停止監(jiān)聽一個(gè)事件,可以直接調(diào)用stopListening,同樣傳入3個(gè)參數(shù):目標(biāo)對(duì)象、事件和事件處理函數(shù)。

          阻止冒泡

          因?yàn)榇蟛糠譃g覽器都是按照DOM Leavl 1綁定事件方式,采用的全都是事件冒泡方式。所以阻止事件冒泡(嵌套元素中傳播)是很有必要的。如下方案:

          阻止冒泡方案:

          function cancelPropagation (event){ event = window.event||event; if( document.all){ event.cancelBubble = true; }else{ event.stopPropagation(); } }

          stopListening函數(shù)使用

          //這里我們采用上面介紹過的事件處理函數(shù) listenEvent 函數(shù) listenEvent(document.getElementById("oBubble2"),"click",function(evt){     cancelPropagation(evt); })
          阻止冒泡

          因?yàn)镮E8、7、6不支持W3C DOM Leavel 2不支持,那么我們就設(shè)置event.cancelBubble 的屬性值為 true;而支持其他現(xiàn)代瀏覽器則使用W3C DOM Leavel 2的,則調(diào)用stopPropagation方法。

          最后羅列文章中出現(xiàn)的幾個(gè)Event方法

          1. W3C DOM Leavl 2綁定和解除事件的方法:addEventListener和removeEventListener:
          2. IE綁定和解除事件的方法:attachEvent和detachEvent
          3. 取消事件:W3C DOM Leavl 2使用preventDefault(),iE直接返回false
          4. 阻止事件在嵌套函數(shù)中傳播(阻止冒泡和捕獲):W3C DOM Leavl 2使用stopPropagation(),IE中cancelBubble返回true

          本文出現(xiàn)所有DEMO下載:js-attachEvent.rar

          posted on 2013-10-08 13:12 Eric_jiang 閱讀(6539) 評(píng)論(0)  編輯  收藏 所屬分類: JavaScript
          主站蜘蛛池模板: 迁西县| 华蓥市| 吉林市| 彝良县| 鄂温| 凤凰县| 广昌县| 沂源县| 龙游县| 兰州市| 双辽市| 盐亭县| 平陆县| 福清市| 南靖县| 大冶市| 平武县| 永川市| 调兵山市| 龙里县| 白水县| 饶阳县| 集贤县| 娱乐| 桓仁| 东源县| 招远市| 红桥区| 新闻| 台山市| 丹东市| 元阳县| 延津县| 塘沽区| 百色市| 昌江| 万载县| 黎平县| 壶关县| 云阳县| 阿克苏市|