摘要:及更早版本不支持事件流。綁定作用域其他的地方,就跟類似,都可以綁定多個(gè)事件處理程序,要?jiǎng)h除只能調(diào)用,并且不能使用匿名函數(shù)的形式。
事件知識(shí)快速入門
事件是前端開發(fā)必備的知識(shí),我通過(guò)閱讀《JavaScript高級(jí)程序設(shè)計(jì)》,梳理了一下整個(gè)事件的知識(shí)體系,下面一起來(lái)學(xué)習(xí)吧。
1. 背景知識(shí)跟所有開發(fā)UI的思路一樣,JavaScript與HTML之間通過(guò)事件來(lái)進(jìn)行交互。事件,就是文檔或?yàn)g覽器窗口中發(fā)生的一些特定的交互瞬間,我們使用監(jiān)聽器(listener/hanlder)來(lái)預(yù)訂事件,當(dāng)事件觸發(fā)時(shí),執(zhí)行相對(duì)應(yīng)的代碼,這種就是傳統(tǒng)軟件工程中被成為觀察者模式的模型,這種模型支持頁(yè)面的行為與頁(yè)面的UI之間的松散耦合。
2. 事件流理解事件流,我們可以從一個(gè)問(wèn)題出發(fā),那就是:頁(yè)面的哪一個(gè)部分會(huì)擁有某個(gè)特定的事件?當(dāng)我們點(diǎn)擊了一個(gè)button時(shí),點(diǎn)擊事件不僅發(fā)生在按鈕上,換句話說(shuō),在單擊按鈕的同時(shí),也是單擊了按鈕的容器元素,甚至也單擊了整個(gè)頁(yè)面。
這便有了事件流的概念,它描述的就是從頁(yè)面中接收事件的順序。而事件流有兩種:
事件冒泡
事件捕獲
早期,IE和Netscape的事件流順序是相反的,IE是事件冒泡流,Netscape是事件捕獲流。
2.1 事件冒泡IE的事件流叫做事件冒泡(event bubbling),即事件開始時(shí)由最具體的元素(文檔中嵌套層次最深的那個(gè)節(jié)點(diǎn))接收,然后逐級(jí)向上傳播到較為不具體的節(jié)點(diǎn)。
例如:
Event Bubbling click
當(dāng)我們點(diǎn)擊頁(yè)面中的div元素時(shí),這個(gè)click事件會(huì)按照如下的順序傳播
IE9、firefox、chrome和safari會(huì)將事件一直冒泡到window對(duì)象。
2.2 事件捕獲NetScape提出的另一種事件流叫做事件捕獲,即是不太具體的節(jié)點(diǎn)應(yīng)該更早接收到事件,而最具體的節(jié)點(diǎn)應(yīng)該最后接收到事件,它的用意在于事件到達(dá)預(yù)定目的之前捕獲它。
還是以上面的html代碼為例子,則當(dāng)我們點(diǎn)擊頁(yè)面的div元素時(shí),這個(gè)click事件的順序?yàn)椋?/p>
2.3 DOM 事件流DOM2級(jí)事件規(guī)定事件流包括三個(gè)階段:
事件捕獲階段,為截獲事件提供了機(jī)會(huì)
處于目標(biāo)階段,實(shí)際的目標(biāo)接收到事件
事件冒泡階段,也可以在這個(gè)階段對(duì)事件作出響應(yīng)
需要注意的有兩點(diǎn):
盡管DOM2級(jí)事件規(guī)范要求事件應(yīng)該從document對(duì)象開始傳播,但是大多數(shù)瀏覽器都是從window對(duì)象開始捕獲的。
DOM2級(jí)明確要求捕獲階段不會(huì)涉及事件目標(biāo),但是IE9,safari,chrome,firefox和opera9.5都會(huì)在捕獲階段觸發(fā)事件對(duì)象上的事件,結(jié)果,就是有兩個(gè)機(jī)會(huì)在目標(biāo)對(duì)象上操作事件。
IE8及更早版本不支持DOM事件流。
3. 事件處理程序事件是用戶或?yàn)g覽器自身執(zhí)行的某種動(dòng)作,而響應(yīng)某個(gè)事件的函數(shù)就叫做事件處理程序。
設(shè)置事件處理程序的方式有4種,以下來(lái)一一介紹。
3.1 HTML事件處理程序某個(gè)元素支持的事件,都可以使用一個(gè)與相應(yīng)事件處理程序同名的HTML屬性來(lái)指定,這個(gè)屬性的值應(yīng)該是能夠執(zhí)行的JavaScript代碼,例如:
我們可以直接在屬性中的js代碼中通過(guò)event變量獲取到event對(duì)象,代碼中的this指的是事件的目標(biāo)元素。
這種方式在很多古老的頁(yè)面中都可以看到,它比較的簡(jiǎn)單,粗暴。但是它導(dǎo)致了HTML與JavaScript代碼緊密耦合,從實(shí)踐的角度上,最好不要采用這樣的形式。
3.2 DOM0級(jí)事件處理程序通過(guò)JavaScript指定的事件處理程序的傳統(tǒng)方式,就是將一個(gè)函數(shù)賦值給一個(gè)事件處理程序?qū)傩浴?/p>
這個(gè)方式有兩個(gè)優(yōu)點(diǎn):
簡(jiǎn)單
跨瀏覽器,至今所有的現(xiàn)代瀏覽器都支持。
var btn = document.getElementById("btn"); btn.onclick = function (event) { alert(event.type); alert(this.id); }
需要注意的是,通過(guò)這個(gè)方式進(jìn)行設(shè)置,我們無(wú)法對(duì)同一個(gè)元素的同一個(gè)事件綁定多個(gè)事件處理程序(會(huì)覆蓋),例如以下代碼,就只會(huì)執(zhí)行最后設(shè)置的函數(shù)。
var btn = document.getElementById("btn"); btn.onclick = function (event) { // 不會(huì)執(zhí)行 alert(event.type); alert(this.id); } btn.onclick = function (event) { alert("覆蓋了"); }
依據(jù)這個(gè)特性,我們可以通過(guò)btn.onclick = null來(lái)刪除設(shè)置的事件處理程序。當(dāng)然我們也可以通過(guò)以下的技巧,來(lái)為其綁定多個(gè)事件處理程序。
var btn = document.getElementById("btn"); btn.onclick = function (event) { alert(event.type); alert(this.id); } var oldHandler = btn.onclick; // 獲取前面設(shè)置的事件處理程序 btn.onclick = function (event) { oldHandler.call(this, event); alert("覆蓋了"); }3.3 DOM2級(jí)事件處理程序
DOM2級(jí)事件定義了兩個(gè)方法,用于處理指定和刪除事件程序的操作
addEventListener(type, listener, isCapture)
removeEventListener(type, listener, isCapture)
它們接收三個(gè)參數(shù):
要處理的事件名(不需要帶on,例如點(diǎn)擊事件是click)
作為事件處理程序的函數(shù)
布爾值,為true時(shí)表示捕獲階段調(diào)用事件處理程序,為false則表示冒泡階段調(diào)用事件處理程序
var btn = document.getElementById("btn"); btn.addEventListener("click", function (event) { alert(event.type); alert(this.id); }, false);
使用這個(gè)方式的主要好處就是可以添加多個(gè)事件處理程序
var btn = document.getElementById("btn"); btn.addEventListener("click", function (event) { alert(event.type); alert(this.id); }, false); btn.addEventListener("click", function (event) { alert("hello world"); }, false);
通過(guò)addEventListener方式添加的事件處理程序只能通過(guò)removeEventListener來(lái)刪除,這就是說(shuō)如果我們采用匿名函數(shù)的方式來(lái)添加事件處理程序的話,則無(wú)法進(jìn)行刪除,因此比較好的方式就是:
var btn = document.getElementById("btn"); function handler(event) { alert(event.type); alert(this.id); } btn.addEventListener("click", handler, false); btn.removeEventListener("click", handler, false);
在大多數(shù)情況下,都是將事件處理程序添加到事件流的冒泡階段,這樣可以最大限度地兼容各種瀏覽器。
3.4 IE事件處理程序IE實(shí)現(xiàn)了與DOM中類似的兩個(gè)方法:
attachEvent(type, listener)
detachEvent(type, listener)
參數(shù)type是on+事件名,如點(diǎn)擊事件,則是onclick
由于IE8及更早版本只支持事件冒泡,所以通過(guò)attachEvent()添加事件處理程序都會(huì)被添加到冒泡階段。
Event Bubbling
上面的代碼其實(shí)是有問(wèn)題的,當(dāng)alert(this.id)時(shí),會(huì)看到結(jié)果為undefined,這就是使用這個(gè)方法特別要注意的地方,事件處理程序會(huì)在全局作用域中運(yùn)行,因此this等于window。
我們可以運(yùn)用一個(gè)小技巧,來(lái)修復(fù)這個(gè)問(wèn)題。
var btn = document.getElementById("btn"); function handler(event) { alert(event.type); alert(this.id); } btn.attachEvent("onclick", function (event){ handler.call(btn, event); // 綁定作用域 });
其他的地方,attachEvent()就跟addEventListener()類似,都可以綁定多個(gè)事件處理程序,要?jiǎng)h除只能調(diào)用detachEvent(),并且不能使用匿名函數(shù)的形式。
支持IE事件處理程序的瀏覽器有IE和Opera
4. 總結(jié)掌握了這些知識(shí)之后,我們就可以動(dòng)手去編寫我們的跨瀏覽器的事件處理程序了^_^
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90963.html
摘要:個(gè)人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開始萌生寫文章的想法,到著手...
摘要:獲取元素距離的位置返回值為對(duì)象獲取相對(duì)于其最近的有定位的父元素的位置。不僅提供了更加優(yōu)雅的事件處理語(yǔ)法,而且極大的增強(qiáng)了事件的處理能力。注冊(cè)簡(jiǎn)單事件表示給綁定事件,并且由自己觸發(fā),不支持動(dòng)態(tài)綁定。 jQuery特殊屬性操作 val方法 val方法用于設(shè)置和獲取表單元素的值,例如input、textarea的值 //設(shè)置值 $(#name).val(張三); //獲取值 $(#name)...
摘要:前端最基礎(chǔ)的就是。幫助從舊的事件方法轉(zhuǎn)換,和。方法移除用綁定的事件處理程序。特定的事件處理程序可以被移除元素上提供事件名稱,命名空間,處理函數(shù)。用于過(guò)濾器的觸發(fā)事件的選擇器元素的后代。事件觸發(fā)模擬觸發(fā)原生使用觸發(fā)。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS)...
摘要:前端最基礎(chǔ)的就是。幫助從舊的事件方法轉(zhuǎn)換,和。方法移除用綁定的事件處理程序。特定的事件處理程序可以被移除元素上提供事件名稱,命名空間,處理函數(shù)。用于過(guò)濾器的觸發(fā)事件的選擇器元素的后代。事件觸發(fā)模擬觸發(fā)原生使用觸發(fā)。 前端最基礎(chǔ)的就是 HTML+CSS+Javascript。掌握了這三門技術(shù)就算入門,但也僅僅是入門,現(xiàn)在前端開發(fā)的定義已經(jīng)遠(yuǎn)遠(yuǎn)不止這些。前端小課堂(HTML/CSS/JS)...
閱讀 1860·2021-09-23 11:21
閱讀 707·2019-08-30 15:55
閱讀 844·2019-08-29 15:40
閱讀 541·2019-08-29 12:56
閱讀 3175·2019-08-26 12:00
閱讀 3567·2019-08-23 18:24
閱讀 2259·2019-08-23 17:08
閱讀 1649·2019-08-23 17:03