Javascript高級編程學習筆記(58)—— 事件(2)事件處理程序
事件處理程序
事件處理程序即響應某個事件的函數
事件處理程序以 “on” 開頭
如“onclick”,“onload”
HTML事件處理程序
某個元素支持的每種事件都可以使用一個與響應的事件處理程序同名的HTML特性來指定
這個特性的值應該是能夠執行的script代碼
如:
<input type="button" value="click me" onclick="alert(‘clicked‘)"/>
此外也可以直接調用在文檔其它部分定義的函數作為事件處理程序所執行的代碼
如:
<input type="button" value="click me" onclick="functionClick()"/>
以這樣的方式指定事件處理程序會創建一個封裝著元素屬性值的函數
該函數有一個局部變量 event (事件對象),通過event變量可以訪問事件對象
並且在這個函數內部,this指向事件的目標元素
此外,這個動態創建的函數內部可以像訪問局部變量一樣訪問document以及該元素本身的成員
這是因為HTML指定的事件處理函數會像下面這樣拓展函數作用域
function(){ with(document){ with(this){ //元素屬性值 } } }
這樣的目的無非是為了讓事件處理程序無需引用表單元素就能訪問其它表單字段
但是這種方式有以下缺點:
- 存在時差問題,即觸發事件時事件處理程序可能並不具備執行條件
- 這樣拓展的事件處理程序作用域鏈在不同的瀏覽器可能會導致不同的結果
- HTML與JS代碼的緊密耦合,使代碼的維護成本增加
DOM0級事件處理程序
通過JS指定事件處理程序的傳統方式是在第四代web瀏覽器出現的,只需要將一個函數賦值給事件處理程序屬性即可
這種方式一直沿用至今,因為這種方法非常簡單並且具備跨瀏覽器優勢
如下所示:
var btn = document.getElementByTagName("button")[0]; btn.onclick = function(){ alert("clicked"); }
使用DOM0級方法指定的事件處理程序被認為是元素方法
因為事件處理程序運行在元素作用域中,所以this引用當前元素
以這種方式定義的事件處理程序會在事件流的冒泡階段被處理
如果需要刪除事件處理程序,只需要將事件處理程序屬性的值設為 null 即可
btn.onclick = null;
DOM2級事件處理程序
“DOM級事件”定義了兩個方法用於指定和刪除事件處理程序
- addEventListener()指定事件處理函數
- removeEventListener()移除事件處理函數
上面兩個方法都接收三個參數
- 要處理的事件名
- 作為事件處理程序的函數
- 布爾值 true 表示在捕獲階段調用事件處理程序 false在冒泡階段調用事件處理程序
與DOM0級一樣DOM2級也是在元素作用域中執行
與DOM0最大的區別在於,DOM2級可以為一個元素添同一事件加多個事件處理程序,而DOM0級重復設置後面的事件處理程序將會覆蓋前面的事件處理程序
DOM2級同一元素的同一事件的事件處理程序被事件觸發時會按照添加順序執行
由 addEventListener()添加的事件只能由 removeEventListener()移除
這也意味著,如果addEventListener添加了匿名函數作為事件處理程序將無法被移除
PS.一般來說為了最大限度地保證瀏覽器兼容,會把事件註冊在事件冒泡階段
IE事件處理程序
IE實現了與DOM中類似地兩個方法:
- attachEvent()
- detachEvent()
這兩個方法接收相同的兩個參數
- 事件名稱
- 事件處理程序函數
由於低版本IE只支持冒泡,所以這兩個方法會將事件處理程序添加到冒泡階段
這裏要註意的是:
- 事件名稱與DOM不一致列如click事件 addEventListener 使用 “click” 而 attachEvent使用“onclick”
- 作用域不同,attachEvent事件添加的函數作用域為全局作用域,所以this等於 window
- 多個事件執行順序不同 與DOM2級相反即與添加事件的順序相反
跨瀏覽器事件處理程序
為了隔離瀏覽器差異,我們可能會使用一些JS庫來完成跨瀏覽器的事件處理程序的兼容
當然我們也可以自己實現
大體實現如下:
// 跨平臺事件綁定 參數 1.目標元素 2.目標事件 3.事件處理函數 function addEvent(ele,eve,fun) { if(ele.addEventListener){ ele.addEventListener(eve,fun,false); }else if(ele.attachEvent){ ele.attachEvent.call(ele,"on"+eve,fun,false); }else{ ele["on"+eve] = fun; } } // 跨平臺事件移除 function removeEvent(ele,eve,fun) { if(ele.removeEventListener){ ele.removeEventListener(eve,fun,false); }else if(ele.detachEvent){ ele.detachEvent.call(ele,"on"+eve,fun,false); }else{ ele["on"+eve] = null; } }
Javascript高級編程學習筆記(58)—— 事件(2)事件處理程序