之前對事件模型還是比較清楚的,許多概念都清晰映射在腦海中。工作之後,一方面使用的 局限性,二是習慣於用框架中的各種事件監聽方式,簡單即方便,久而久之,事件的一些概念開 始淡出記憶中,就像我現在已經開始淡忘C語言的指針、麥克斯韋方程組、矩陣的變換、最小二乘 法等。知識就像五彩繽紛的鵝卵石鋪墊在你前行的 ...
之前對事件模型還是比較清楚的,許多概念都清晰映射在腦海中。工作之後,一方面使用的
局限性,二是習慣於用框架中的各種事件監聽方式,簡單即方便,久而久之,事件的一些概念開
始淡出記憶中,就像我現在已經開始淡忘C語言的指針、麥克斯韋方程組、矩陣的變換、最小二乘
法等。知識就像五彩繽紛的鵝卵石鋪墊在你前行的道路上,從簡單到深刻,從深刻到領悟,一直
助你漸行漸遠。回頭看看事件模型唄。
一、事件簡簡介
事件包括:
滑鼠事件
鍵盤事件
框架事件 onerror onresize onscroll等
表單事件事件 onblur onfocus等
剪貼板事件 oncopy oncut onpaste
列印事件 onafterprint onbeforeprint
拖動事件 ondrag ondragenter等
media事件 onplay onpause
動畫事件 animationend
過渡事件
其他事件等
事件被封裝成對象,包括
目標事件對象
事件監聽對象
滑鼠事件對象
鍵盤事件對象等
他們包含了各自的屬性和方法,也繼承自Event這個對象。具體看你W3C就OK了。
常用方法:
event. preventDefault()//阻止元素預設的行為,如鏈接的跳轉、表單的提交;
event. stopPropagation()//阻止事件冒泡
二、事件的三種模型
1、原始事件模型(DOM0級)
特點:原始事件模型中,事件發生後沒有傳播的概念,沒有事件流。事件發生,立即處理。
監聽函數只是元素的一個屬性值,通過指定元素的屬性值來綁定監聽器。書寫方式有兩種:
HTML: <input id=”btn” onclick=”func()” />
js : document.getElementsById(‘btn’).onclick = func
優點:所有瀏覽器都相容
缺點:
a、邏輯與顯示沒有分離;
b、相同事件的監聽函數只能綁定一個,後綁定的會覆蓋掉前面的。
c、無法通過事件的冒泡、委托等機制等。
在當前web程式模塊化開發以及更加複雜的邏輯狀況下,這種方式顯然已經落伍了,所以在真
正項目中不推薦使用,平時寫點demo倒是可以,速度比較快。
2、IE事件模型
特點:IE是將event對象在處理函數中設為window的屬性,一旦函數執行結束,便被置為null
了。
IE的事件模型只有兩步,先執行元素的監聽函數,然後事件沿著父節點一直冒泡到document。
綁定解除監聽函數的方法:
attachEvent( "eventType","handler"),其中evetType為事件的類型,如onclick,註意要加
’on’。
解除事件監聽器的方法是 detachEvent("eventType","handler" );
缺點:就是只能IE自己用,太高冷了。
3、 DOM2事件模型
在 W3C 2 級 DOM 事件中規範了事件模型,即 DOM2事件模型。現代瀏覽器(IE9以下不算)都遵
循了這個規範。
特點:
W3C制定的事件模型中,一次事件的發生包含三個過程:
a、事件捕獲階段。事件被從document一直向下傳播到目標元素,在這過程中依次檢查經過的節
點是否註冊了該事件的監聽函數,若有則執行。
b、事件處理階段。事件到達目標元素,執行目標元素的事件處理函數.
c、事件冒泡階段。事件從目標元素上升一直到達document,同樣依次檢查經過的節點是否註冊
了該事件的監聽函數,有則執行。
註意:所有的事件類型都會經歷事件捕獲階段,但是只有部分事件會經歷事件冒泡階段,例如
submit事件就不會被冒泡。
綁定解除監聽函數的方法:
addEventListener("eventType","handler","true|false");其中eventType指事件類型,註意
不要加‘on’首碼,與IE下不同。
第二個參數是處理函數,
第三個即用來指定是否在捕獲階段進 true捕獲階段 false 只有冒泡階段
監聽器的解除也類似:removeEventListner("eventType","handler","true!false");
相容IE和現代瀏覽器的事件註冊監聽寫法
var a = document.getElementById('XXX'); if(a.attachEvent){ a.attachEvent('onclick',func); } else{//IE9以上和主流瀏覽器 a.addEventListener('click',func,false); }
現有的框架和類庫都會對適應各種瀏覽器做相容性的封裝,JQuery底層即使用了上面的相容性寫法。
三、事件的捕獲-冒泡機制
DOM2標準中,一次事件的完整過程包括三步:捕獲→執行目標元素的監聽函數→冒泡,在捕獲和
冒泡階段,會依次檢查途徑的每個節點,如果該節點註冊了相應的監聽函數,則執行監聽函數。
以如下HTML結構為例子,執行流程應該是這樣的:
<div id="parent"> 父元素 <div id="child">子元素</div> </div>
運行一下一目瞭然。
var parent= document.getElementById('parent'); console.dir(parent); var child = document.getElementById('child'); parent.addEventListener('click',function(){alert('父親在捕獲階段被點 擊');},true);//第三個參數為true child.addEventListener('click',function(){alert('孩子被點擊了');},false); parent.addEventListener('click',function(){alert('父親在冒泡階段被點擊 了');},false);//第三個參數為false
可以看到,第三個即用來指定是否在捕獲階段進 true捕獲階段,false沒有捕獲階段 。
如果不想讓事件向上冒泡,可以在監聽函數中調用event.stopPrapagation()來完成,後面會有應
用的慄子。
四、事件委托機制
委托就是把事件監聽函數綁定到父元素上,讓它的父輩來完成事件的監聽,這樣就把事情“委托
”了過去。在父輩元素的監聽函數中,可通過event.target屬性拿到觸發事件的原始元素,然後
再對其進行相關處理。
五、jQuery中的事件監聽方式
jQuery中提供了四種事件監聽方式,分別是bind、live、delegate、on,對應的解除監聽的
函數分別是unbind、die、undelegate、off。這幾個方法已經對各種瀏覽器的相容性進行封裝。
具體方法可以查看手冊。
註意幾點:
jQuery推薦事件的綁定都使使用on方法
jQuery預設事件不在捕獲中進行
六、什麼是自定義事件
張鑫旭的《js-dom自定義事件》
七、一個簡單例子
點擊彈窗之外任何地方,彈框關閉。
方法:給body綁定事件,在事件的執行函數里關閉彈框;
給彈框元素綁定點擊事件,在事件的執行函數裡面組織事件冒泡,即:
event.stopPrapagation();