事件類型
Web瀏覽器可能發(fā)生的事件類型有很多。不同的事件類型具有不同的信息时呀,而“DOM3級(jí)事件“規(guī)定了以下幾類事件蹦骑。
- UI(User Interface,用戶界面)事件禀酱,當(dāng)用戶與頁(yè)面上的元素交互時(shí)觸發(fā)憔维;
- 焦點(diǎn)事件,當(dāng)元素獲得或失去焦點(diǎn)時(shí)觸發(fā)畏邢;
- 鼠標(biāo)事件业扒,當(dāng)用戶通過(guò)鼠標(biāo)在頁(yè)面執(zhí)行操作時(shí)觸發(fā);
- 滾輪事件舒萎,當(dāng)使用鼠標(biāo)滾輪(或類似設(shè)置)時(shí)觸發(fā)程储;
- 文本事件,當(dāng)在文檔中輸入文本時(shí)觸發(fā)臂寝;
- 鍵盤事件章鲤,當(dāng)用戶通過(guò)包租在頁(yè)面上執(zhí)行操作時(shí)觸發(fā);
- 合成事件交煞,當(dāng)為IME(Input MethodEditor咏窿,輸入法編輯器)輸入字符時(shí)觸發(fā);
- 變動(dòng)(mutation)事件素征,當(dāng)?shù)讓覦OM結(jié)構(gòu)發(fā)生變化時(shí)觸發(fā)集嵌;
- 變動(dòng)名稱事件,當(dāng)元素或?qū)傩悦儎?dòng)時(shí)觸發(fā)御毅。此類事件已經(jīng)被廢棄根欧,沒(méi)有任何瀏覽器實(shí)現(xiàn)它們,因此本章不做介紹端蛆。
除了這幾類事件之外凤粗,HTML5也定義了一組事件,而有此瀏覽器還會(huì)在DOM和BOM中實(shí)現(xiàn)其他專有事件今豆。這些專有的事件一般都是根據(jù)開(kāi)發(fā)人員需求定制的嫌拣。沒(méi)有什么規(guī)范,因此不同瀏覽器的實(shí)現(xiàn)有可能不一致呆躲。
DOM2級(jí)事件模塊在DOM2級(jí)事件模塊基礎(chǔ)上重新這些事件异逐,也添加了一些新事件。包括IE9在內(nèi)的所有主流瀏覽器都支持DOM2級(jí)事件插掂。IE9也支持DOM3級(jí)事件灰瞻。
UI事件
UI事件 批的是那些不一定與用戶操作有關(guān)的事件。這些事件在DOM規(guī)范出現(xiàn)之前辅甥,都是以這種或那種形式存在的酝润。而在DOM規(guī)范中保留是為了向后兼容。現(xiàn)有的UI的事件如下.
- DOMActivate:表示元素已經(jīng)被用戶操作(通過(guò)鼠標(biāo)或鍵盤)激活璃弄。這個(gè)事件在DOM3級(jí)事件中被廢棄要销,但FireFox2+和Chrome支持它∠目椋考慮到不同瀏覽器實(shí)現(xiàn)的差異 蕉陋,不建議使用這個(gè)事件捐凭。
- load:當(dāng)頁(yè)面完全加載后在window上面觸發(fā),當(dāng)所有框架都加載完畢時(shí)在框架集上面觸發(fā)凳鬓,當(dāng)圖像加載完畢時(shí)在
<img>
元素上面觸發(fā)茁肠。或者當(dāng)嵌入的內(nèi)容加載完畢時(shí)在元素上面觸發(fā)缩举。 - unload:當(dāng)頁(yè)面完全卸載后在window上面觸發(fā)垦梆,當(dāng)所有框架都卸載后在框架集上面觸發(fā),或者當(dāng)嵌入的內(nèi)容卸載完畢后在元素上面觸發(fā)仅孩。
- abort:在用戶停止下載過(guò)程時(shí)托猩,如果嵌入的內(nèi)容沒(méi)有加載完,則在元素上面觸發(fā)辽慕。
- error: 當(dāng)發(fā)生JavasScript錯(cuò)誤時(shí)在window上面觸發(fā)京腥,當(dāng)無(wú)法加載圖片時(shí)在
<img>
元素上面觸發(fā),當(dāng)元素加載嵌入內(nèi)容時(shí)在元素上面觸發(fā)溅蛉,或者當(dāng)有一或多個(gè)框架無(wú)法加載時(shí)在框架集上面觸發(fā)公浪。 - select: 當(dāng)用戶選擇文本框( or )中的一個(gè)可多個(gè)字符時(shí)觸發(fā)。
- resize: 當(dāng)窗口或框架的大小變化時(shí)在window或框架上面觸發(fā)船侧;
- scroll:當(dāng)用戶流動(dòng)帶有流動(dòng)條的元素中的內(nèi)容時(shí)欠气,在該元素上面觸發(fā)。元素中包含所加載頁(yè)面的流動(dòng)條镜撩。
多數(shù)這些事件都與window對(duì)象或表彰控件相關(guān)预柒。
除了DOMActivate之外,其他事件都在DOM2級(jí)事件中都?xì)w為HTML事件(DOMActivate在DOM2級(jí)中仍然屬于UI事件)袁梗。在確定瀏覽器是否支持DOM2級(jí)事件規(guī)定的HTML事件宜鸯,可以使用如下代碼:
var isSupported = document.implementation.hasFeature('HTMLEvents',"2.0");
注意,只有根據(jù)“DOM2級(jí)事件”實(shí)現(xiàn)這此事件的瀏覽器才會(huì)返回true遮怜。而以非標(biāo)準(zhǔn)方式支持這些事件的瀏覽器則會(huì)返回false顾翼。要確定瀏覽器是否支持“DOM3級(jí)事件”定義的事件,可以使用如下代碼:
var isSupported = document.implementation.hasFeature('HTMLEvents',"3.0");
1奈泪、load事件
JavaScript中最常用的一個(gè)事件就是load。當(dāng)頁(yè)面完全載后(包括所有圖像灸芳、JavasScript文件涝桅、CSS文件等外部資源),就會(huì)觸發(fā)window上面的load事件烙样。有二種定義onload事件處理程序的方式冯遂。
第一種方式是使用如下所示的JavasScript代碼:
EventUtil.addHandler(window,'load', function(event){
alert("Loaded");
})
//注意EventUtil對(duì)象是自定義封裝的一個(gè)對(duì)象
這是通過(guò)JavasScript來(lái)指定事件處理程序的方式,使用了本章前面定義的跨瀏覽器的EventUtil對(duì)象谒获。與添加其他事件一樣蛤肌,這里也給事件處理程序傳入了一個(gè)event對(duì)象壁却。這個(gè)event對(duì)象中不包含有關(guān)這個(gè)事件的任何附加信息,但兼容DOM的瀏覽器中裸准,event.target屬性的值會(huì)被設(shè)置為document.而IE并不會(huì)為這個(gè)事件設(shè)置srcElement屬性展东。
第二種指定onload事件處理程序的方式是為元素添加一個(gè)onload特性,如下面例子所示:
<body onload="alert('Loaded')">
</body>
一般來(lái)說(shuō)炒俱,在window上面發(fā)生的任何事件都可以在元素中通過(guò)相應(yīng)的特性來(lái)指定盐肃。因?yàn)樵贖TML中無(wú)法訪問(wèn)window元素。初階上权悟,這只是為了保證向后兼容的一種權(quán)宜之計(jì)砸王,但所有瀏覽器都能很好地支持這種方式。我們建議讀者盡可能使用javascript方式峦阁。
根據(jù)“DOM2級(jí)事件”規(guī)范谦铃,應(yīng)該在document而非window上面觸發(fā)load事件,但是榔昔,所有瀏覽器都在window上面實(shí)現(xiàn)了該事件驹闰,以確保向后兼容。
圖像上面也可以觸發(fā)load事件件豌,無(wú)論是在DOM中的圖像還是HTML中的圖像元素疮方。 可以在HTML中為任何圖像指定onload事件處理程序,例如:
<img src="smile.gif" onload="alert('Image loaded')">
這樣茧彤,當(dāng)例子中的圖像加載完畢后就會(huì)顯示一個(gè)警告框骡显。同樣的功能也可以使用JavasScript來(lái)實(shí)現(xiàn),例如:
var image = document.getElementById('myImage');
EventUtil.addHandler(img,'load', function(evnet){
event = EventUtil.getEvent(event);
alert(EventUtil.getTarget(event).src);
})
這里曾掂,使用JavasScript指定了onload事件處理程序惫谤。同時(shí)民傳入了event對(duì)象,盡管它也不包含什么有用的信息珠洗。不過(guò)溜歪,事件的目標(biāo)是<img>元素⌒肀停可以通過(guò)src屬性訪問(wèn)并顯示該 信息蝴猪。
在創(chuàng)建新的<img>元素時(shí),可以為其指定一個(gè)事件處理程序膊爪,以便圖像加載完畢后給出提示自阱。此時(shí),最重要在指定src屬性之前先指定事件米酬,如下面的例子所示沛豌。
EventUtil.addHandler(window,'load', function(){
var image = document.getElementById('myImage');
EventUtil.addHandler(img,'load', function(){
event = EventUtil.getEvent(event);
alert(EventUtil.getTarget(event).src);
});
document.body.appendChild(image);
image.src = 'smile.gif';
})
在這個(gè)例子中,首先為window指定了onload事件處理程序赃额。原因在于,我們是想向DOM中添加一個(gè)新元素加派,所以必須確定頁(yè)面已經(jīng)加載完畢——如果在頁(yè)面加載前操作document.body會(huì)導(dǎo)致錯(cuò)誤叫确。然后,創(chuàng)建了一個(gè)新的圖像元素芍锦,并設(shè)置了其onload事件處理程序竹勉。最后又將這個(gè)圖片添加到頁(yè)面中,還設(shè)置了它的src屬性醉旦。這里有一點(diǎn)需要格外注意:新圖像元素不一定要從添加到文檔后才開(kāi)始下載饶米,只要設(shè)置了src屬性就會(huì)開(kāi)始下載。
同樣的功能也可以通過(guò)使用DOM0級(jí)的Image對(duì)象實(shí)現(xiàn)车胡。在DOM出現(xiàn)之前檬输,開(kāi)發(fā)人員經(jīng)常使用Image對(duì)象在客戶端預(yù)先加載圖像⌒偌可以像使用<img>
一樣使用Image對(duì)象丧慈,只不過(guò)無(wú)法將其添加到DOM樹(shù)中。下面看一個(gè)例子:
EventUtil.addHandler(window,'load', function(){
var image = new Image();
EventUtil.addHandler(img,'load', function(){
alert("Image loaded!");
});
image.src = 'smile.gif';
})
在此主卫,我們使用Image構(gòu)造函數(shù)創(chuàng)建了一個(gè)新圖像的實(shí)例逃默,然后又為它指定了事件處理程序。有的瀏覽器將Image對(duì)象實(shí)現(xiàn)了<img>
元素簇搅,但并非所有瀏覽器都如此完域,所以最好將它們區(qū)別對(duì)待。
在不屬于DOM文檔的圖像(包括未添加到文檔的元素和Image對(duì)象)上觸發(fā)load事件時(shí)瘩将,IE8及之前版本不會(huì)生成event對(duì)象吟税。IE9修復(fù)了這個(gè)問(wèn)題
還有一些元素也以非標(biāo)準(zhǔn)的方式支持load事件。在ie9+ foxfire Opera Chrome和Safari3+及更高版本中姿现。<script>
元素也會(huì)觸發(fā)load事件肠仪,以便 開(kāi)發(fā)人員確定動(dòng)態(tài)加載的JavasScript文件是否加載完畢。 與圖像不同备典,只有在設(shè)置了<script>
元素的src屬性并將該元素添加到文檔后异旧,才會(huì)開(kāi)始下載JavasScript文件。換句放說(shuō)提佣,對(duì)于元素而言吮蛹,指定src屬性和指定事件處理程序的先后順序就不重要了,所有代碼展示了怎樣為<script>
元素指定事件處理程序拌屏。
EventUtil.addHandler(window,'load', function(){
var script = document.createElement('script');
EventUtil.addHandler(script,'load', function(){
alert('Loaded');
});
script.src = "examplte.js";
document.body.appendChild(script);
})
這個(gè)例子使用了跨瀏覽器的EventUtil對(duì)象為新創(chuàng)建的<script>元素指定了onload事件處理程序潮针。此時(shí),大多數(shù)瀏覽器中event對(duì)象的target屬性引用的都是<script>節(jié)點(diǎn)槐壳,而Foxfire3之前的版本中,引用的則是document喜每。IE8及更早版本不支持<script>元素上的load元素务唐。
IE和Opera還支持<link>元素上的load事件雳攘,以便開(kāi)發(fā)人員確定樣式表是否加載完畢。例如:
EventUtil.addHandler(window,'load', function(){
var link = document.createElement('link');
link.type="text/css";
link.rel="stylesheet";
EventUtil.addHandler(link,'load', function(){
alert('css Loaded');
});
link.src = "examplte.css";
document.getElementsByTagName('head')[0].appendChild(link);
})
與<script>
節(jié)點(diǎn)類似枫笛,在未指定href屬性并將<link>
元素添加到文檔之前也不會(huì)開(kāi)始下載樣式表吨灭。
2、unload事件
與load事件對(duì)應(yīng)的是 unload事件刑巧,這個(gè)事件在文檔被完全卸載后觸發(fā)喧兄。只要用戶從一個(gè)頁(yè)面切換到另一個(gè)頁(yè)面,就會(huì)發(fā)生unload事件啊楚。而利用這個(gè)事件最多的情況是清除引用吠冤,以避免內(nèi)在泄漏。與load事件類似恭理,也兩種指定onunload事件處理程序方式拯辙。第一種方式是使用JavasScript,如下所示:
EventUtil.addHandler(window,'unload', function(){
alert('Unloaded');
})
此時(shí)生成的event對(duì)象在兼容DOM的瀏覽器中只包含target屬性(值為document)颜价。IE8及之前版本則為這個(gè)事件對(duì)象提供了srElement屬性涯保。
指定事件處理程序的第二種方式,民是為<body>元素添加一個(gè)特性(與load事件相似)周伦,如下面的例子所示:
<body onunload="alert("Unloaded")"></body>
無(wú)論使用哪種方式夕春,都要小心編寫(xiě)onunload事件處理程序中的代碼。既然unload事件是在一切都被卸載后才觸發(fā) 专挪,那么在頁(yè)面加載后存在的那些對(duì)象及志,此時(shí)就不一定存在了。此時(shí)狈蚤,操作DOM節(jié)點(diǎn)或元素的樣式就會(huì)導(dǎo)致錯(cuò)誤困肩。
根據(jù)“DOM2級(jí)事件”,應(yīng)該在<body>元素而非window對(duì)象上面觸發(fā)unload事件脆侮。不過(guò)所有瀏覽器都在window上實(shí)現(xiàn)了unload事件锌畸,以確保向后兼容。
3靖避、resize事件
當(dāng)瀏覽器窗口被調(diào)整到一個(gè)新的高度或?qū)挾葧r(shí)潭枣,就會(huì)觸發(fā)resize事件。這個(gè)事件在window(窗口)上面觸發(fā)幻捏,因此可以通過(guò)JavasScript或者<bdoy>
元素中的onresize特性來(lái)指定事件處理程序盆犁。如前所述,我們還是推薦使用如下所示的JavasScript方式:
EventUtil.addHandler(window,'resize', function(){
alert('Resizeed');
})
與其他發(fā)生在window上的事件類似篡九,在兼容DOM的瀏覽器中谐岁,傳入事件處理程序中event對(duì)象有一個(gè)target屬性,值為document;而IE8及之前版本則未提供任何屬性伊佃。
關(guān)于何時(shí)會(huì)觸發(fā)resize事件窜司,不同瀏覽器有不同的機(jī)制。IE Safari Chrome 和 Opera會(huì)在瀏覽器窗口變化了1像素時(shí)就觸發(fā) resize事件航揉,然后隨著變化不斷重復(fù)觸發(fā)塞祈。FIrefox則只會(huì)在用戶停止調(diào)整窗口變化時(shí)才會(huì)觸發(fā) resize事件。由于 存在這個(gè)差別帅涂,應(yīng)該注意不要在這個(gè)事件的處理程序中加入大計(jì)算的代碼议薪。因?yàn)檫@些代碼有可能被頻繁執(zhí)行,從而導(dǎo)致瀏覽器反應(yīng)明顯變慢媳友。
瀏覽器窗口最小化或最大化時(shí)也會(huì)觸發(fā) resize事件
4斯议、scroll事件
雖然scroll事件是在window對(duì)象上發(fā)生的,但它實(shí)際表示的則是頁(yè)面中相應(yīng)元素的變化庆锦。在混雜模式下捅位,可以通過(guò) <body>元素的scrollLeft和scrollTop來(lái)監(jiān)控到這一變化;而在標(biāo)準(zhǔn) 模式下搂抒,除Safari之外的所有瀏覽器都會(huì)通過(guò)<html>元素來(lái)反映這一變化(Safari仍然基于<body>跟蹤滾動(dòng)位置)艇搀,如下面的例子所示:
EventUtil.addHandler(window,'scroll', function(){
if(documnent.compatMode == 'CSS1Compat') {
alert(document.documentElement.scrollTop);
} else {
alert(document.body.scrollTop);
}
})
以上代碼指定的事件處理程序會(huì)輸出頁(yè)面的垂直滾動(dòng)位置—–根據(jù)呈現(xiàn)模式不同使用了不同的元素。 由于 Safari3.1之前的版本不支持document.compatMode求晶,因此舊版本的瀏覽器就不會(huì)滿足第二個(gè)條件焰雕。
與resize事件類似,scroll事件也會(huì)在文檔被滾動(dòng)期間重復(fù)被觸發(fā)芳杏,所以有必要盡量保持事件處理程序的代碼簡(jiǎn)單矩屁。