事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Event Exam</title>
</head>
<body>
    <div id="event" onclick="test()"></div>

</body>
</html>

一、事件流,三種事件流。
事件即用戶或?yàn)g覽器自身執(zhí)行的某種動作。
1.事件冒泡 IE中的事件流
click事件由近即遠(yuǎn) div--body--html--document


冒泡事件.png

2.事件捕獲
document--html--body--div


捕獲流.png

3.DOM事件流
捕獲事件事件到body層就停止了,不會傳到div層,然后開始事件冒泡在傳回document。


DOM事件流.png
IE9、Opera、Firefox、Chrome和Safari都支持DOM事件流;IE8及更早版本不支持DOM事件流。

二、事件處理程序
即響應(yīng)某個(gè)事件的函數(shù)就叫做事件處理程序。事件處理程序的名字以"on"開頭。
1.HTML事件處理程序
直接在html中綁定事件

<input type="button" value="Click Me" onclick="alert('Clicked')" />

這樣會創(chuàng)建一個(gè)封裝著元素屬性值的函數(shù),該函數(shù)中有一個(gè)局部變量event,也就是事件對象。

<!--輸出 click -->
<input type="button" value="Click Me" onclick="alert(event.type)" />

通過event變量,可以直接訪問事件對象,在這個(gè)函數(shù)內(nèi)部,this值等于事件的目標(biāo)元素。

<!--輸出 Click Me -->
<input type="button" value="Click Me" onclick="alert(this.value)" />

event 函數(shù)內(nèi)擴(kuò)展作用域的方式

可以輸出value
 <input type="button" value="Click Me" onclick="alert(value)" />
<form method="post">
        <input type="text" name="username" value="">
        <input type="button" onclick="alert(username.value)">
</form>

缺點(diǎn):
存在一個(gè)時(shí)差問題。因?yàn)橛脩艨赡軙贖TML元素一出現(xiàn)在頁面上就觸發(fā)相應(yīng)的事件,但當(dāng)時(shí)的事件處理程序有可能尚不具備執(zhí)行條件。
這樣擴(kuò)展事件處理程序的作用域鏈在不同瀏覽器中會導(dǎo)致不同結(jié)果。不同JavaScript引擎遵循的標(biāo)識符解析規(guī)則略有差異,很可能會在訪問非限定對象成員時(shí)出錯(cuò)。
HTML與JavaScript代碼緊密耦合。

2.DOM0級事件處理程序
對每個(gè)事件只支持一個(gè)事件處理程序

var btn = document.getElementById("myBtn");
btn.onclick = function () {
    alert(this.id);
}
//刪除點(diǎn)擊事件
btn.onclick = null;
 <input type="button" value="Click Me" onclick="null" />
如果使用HTML指定事件處理程序,將相應(yīng)的屬性值設(shè)置為null,也可以刪除以這種方式指定的事件處理程序。

3.DOM2級事件處理程序
“DOM2級事件”定義了兩個(gè)方法,用于處理指定和刪除事件處理程序的操作:addEventListener()和removeEventListener()。所有DOM節(jié)點(diǎn)中都包含這兩個(gè)方法,并且它們都接受3個(gè)參數(shù):

  • 1 事件名,
  • 2 事件處理程序,
  • 3 一個(gè)布爾值(true,表示在捕獲階段調(diào)用時(shí)間處理程序,false,表示在冒泡階段調(diào)用時(shí)間處理程序)
btn.addEventListener("click",function () {
    alert(this.id);
},false)
btn.addEventListener("click",function () {
    alert("hello World");
},false)

優(yōu)點(diǎn):使用DOM2可以添加多個(gè)事件處理程序,按添加方法的順序執(zhí)行。

移除點(diǎn)擊事件,需要將定義的事件提出來,移除的事件和添加的事件應(yīng)為同一個(gè)事件。

function handle() {
        alert(this.id);
}
btn.addEventListener("click",handle,false)
btn.removeEventListener("click",handle,false)

大多數(shù)情況下,都是將事件處理程序添加到事件流的冒泡階段,這樣可以最大限度地兼容各種瀏覽器。最好只在需要在事件到達(dá)目標(biāo)之前截獲它的時(shí)候?qū)⑹录幚沓绦蛱砑拥讲东@階段。如果不是特別需要,我們不建議在事件捕獲階段注冊事件處理程序。

4.IE事件處理程序
IE中實(shí)現(xiàn)了與DOM中類似的方法,attachEvent()和detachEvent()。這兩個(gè)方法接受相同的兩個(gè)參數(shù):事件處理程序名稱與事件處理程序函數(shù)。由于IE8及更早版本只支持事件冒泡,所以通過attachEvent()添加的事件處理程序都被添加到冒泡階段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
      alert(this==window);//true
})

在IE中使用attachEvent()和在DOM0級方法的主要區(qū)別
在于事件處理程序的作用域。attachEvent()的事件處理程序在全局中作用域運(yùn)行,在DOM0級方法的情況下,事件處理程序是局部的。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick",function(){
      alert(this==window);//true
})
btn.attachEvent("onclick",function(){
      alert("Hello World");
})
//與DOM方法不同的事,IE中不是按添加方法的順序執(zhí)行,而是相反的執(zhí)行,先輸出Hello World,在輸出true

attachEvent()添加的方法可以用detachEvent()方法移除,條件是必須提供相同的參數(shù),與DOM方法一致,不能刪除匿名函數(shù)。

支持IE事件處理程序的瀏覽器只有IE和Opera。

5.跨瀏覽器的事件處理程序
三、事件對象
1.DOM的事件處理對象
兼容DOM的瀏覽器會將一個(gè)event對象傳入到事件處理程序中。

var btn = document.getElementById("myBtn");
btn.onclick = function (event) {
    alert("點(diǎn)我");
}
event屬性2.png
event屬性.png

只有在事件處理程序執(zhí)行期間,event對象會存在,一旦時(shí)間處理程序執(zhí)行完,event對象就會被銷毀。

2.IE中的事件對象
使用DOM0級方法添加事件處理程序時(shí),event對象作為window對象的屬性存在。
使用attachEvent()添加的,就會有一個(gè)event對象作為參數(shù)被傳入事件處理函數(shù)。
3.跨瀏覽器的事件對象
四、事件類型

  • UI(User Interface,用戶界面)事件,當(dāng)用戶與頁面上的元素交互時(shí)觸發(fā);
  • 焦點(diǎn)事件,當(dāng)元素獲得或失去焦點(diǎn)時(shí)觸發(fā);
  • 鼠標(biāo)事件,當(dāng)用戶通過鼠標(biāo)在頁面上執(zhí)行操作時(shí)觸發(fā);
  • 滾輪事件,當(dāng)使用鼠標(biāo)滾輪(或類似設(shè)備)時(shí)觸發(fā);
  • 文本事件,當(dāng)在文檔中輸入文本時(shí)觸發(fā);
  • 鍵盤事件,當(dāng)用戶通過鍵盤在頁面上執(zhí)行操作時(shí)觸發(fā);
  • 合成事件,當(dāng)為IME(Input Method Editor,輸入法編輯器)輸入字符時(shí)觸發(fā);
  • 變動(mutation)事件,當(dāng)?shù)讓覦OM結(jié)構(gòu)發(fā)生變化時(shí)觸發(fā)。
    1.UI事件
  • load: 當(dāng)頁面完全加載后在window上面觸發(fā),當(dāng)所有框架都加載完畢時(shí)在框架集上面觸發(fā),當(dāng)圖像加載完畢時(shí)在<img>元素上面觸發(fā),或者當(dāng)嵌入的內(nèi)容加載完畢時(shí)在<object>元素上面觸發(fā)。
  • unload:當(dāng)頁面完全卸載后在window上面觸發(fā),當(dāng)所有框架都卸載后在框架集上面觸發(fā),或者當(dāng)嵌入的內(nèi)容卸載完畢后在<object>元素上面觸發(fā)。
  • abort:在用戶停止下載過程時(shí),如果嵌入的內(nèi)容沒有加載完,則在<object>元素上面觸發(fā)。
  • error:當(dāng)發(fā)生JavaScript錯(cuò)誤時(shí)在window上面觸發(fā),當(dāng)無法加載圖像時(shí)在<img>元素上面觸發(fā),當(dāng)無法加載嵌入內(nèi)容時(shí)在<object>元素上面觸發(fā),或者當(dāng)有一或多個(gè)框架無法加載時(shí)在框架集上面觸發(fā)。
  • select:當(dāng)用戶選擇文本框(<input>或<tex-terea>)中的一或多個(gè)字符時(shí)觸發(fā)。
  • resize:當(dāng)窗口或框架的大小變化時(shí)在window或框架上面觸發(fā)。
  • scroll:當(dāng)用戶滾動帶滾動條的元素中的內(nèi)容時(shí),在該元素上面觸發(fā)。<body>元素中包含所加載頁面的滾動條。
//load 事件 兩種添加方式,EventUtil為跨瀏覽器的事件對象。
在body元素上加onload="alert('hello')"事件,
EventUtil.addHandler(window, "load", function(event){
            alert("Loaded!");
});
//unload 事件,用戶從一個(gè)頁面切換到另一個(gè)頁面觸發(fā)。
在body元素上加onunload="alert('hello')"事件,
EventUtil.addHandler(window, "unload", function(event){
            alert("Loaded!");
});
//resize事件,當(dāng)瀏覽器被調(diào)整到一個(gè)新的高度或?qū)挾葧r(shí),會觸發(fā)。
EventUtil.addHandler(window, "resize", function(event){
           var event = EventUtil.getEvent(event);
           var pageX = event.pageX;
           var pageY = event.pageY;
});
//scroll 事件
EventUtil.addHandler(window, "scroll", function(event){
            alert("Loaded!");
});

2.焦點(diǎn)事件

  • blur:在元素獲得焦點(diǎn)時(shí)觸發(fā)。這個(gè)事件不會冒泡,所有瀏覽器都支持。
  • focus:在元素獲得焦點(diǎn)時(shí)觸發(fā)。這個(gè)事件不會冒泡;所有瀏覽器都支持它。

3.鼠標(biāo)事件和滾輪事件
DOM3級事件中定義了9個(gè)鼠標(biāo)事件:

  • click:在用戶單擊主鼠標(biāo)按鈕(一般是左邊的按鈕)或者按下回車鍵時(shí)觸發(fā)。這一點(diǎn)對確保易訪問性很重要,意味著onclick事件處理程序既可以通過鍵盤也可以通過鼠標(biāo)執(zhí)行。
  • dblclick:在用戶雙擊主鼠標(biāo)按鈕(一般是左邊的按鈕)時(shí)觸發(fā)。從技術(shù)上說,這個(gè)事件并不是DOM2級事件規(guī)范中規(guī)定的,但鑒于它得到了廣泛支持,所以DOM3級事件將其納入了標(biāo)準(zhǔn)。
  • mousedown:在用戶按下了任意鼠標(biāo)按鈕時(shí)觸發(fā)。不能通過鍵盤觸發(fā)這個(gè)事件。
  • mouseenter:在鼠標(biāo)光標(biāo)從元素外部首次移動到元素范圍之內(nèi)時(shí)觸發(fā)。這個(gè)事件不冒泡,而且在光標(biāo)移動到后代元素上不會觸發(fā)。DOM2級事件并沒有定義這個(gè)事件,但DOM3級事件將它納入了規(guī)范。IE、Firefox9+和Opera支持這個(gè)事件。
  • mouseleave:在位于元素上方的鼠標(biāo)光標(biāo)移動到元素范圍之外時(shí)觸發(fā)。這個(gè)事件不冒泡,而且在光標(biāo)移動到后代元素上不會觸發(fā)。DOM2級事件并沒有定義這個(gè)事件,但DOM3級事件將它納入了規(guī)范。IE、Firefox9+和Opera支持這個(gè)事件。
  • mousemove:當(dāng)鼠標(biāo)指針在元素內(nèi)部移動時(shí)重復(fù)地觸發(fā)。不能通過鍵盤觸發(fā)這個(gè)事件。
  • mouseout:在鼠標(biāo)指針位于一個(gè)元素上方,然后用戶將其移入另一個(gè)元素時(shí)觸發(fā)。
  • mouseover:在鼠標(biāo)指針位于一個(gè)元素外部,然后用戶將其首次移入另一個(gè)元素邊界之內(nèi)時(shí)觸發(fā)。不能通過鍵盤觸發(fā)這個(gè)事件。
  • mouseup:在用戶釋放鼠標(biāo)按鈕時(shí)觸發(fā)。不能通過鍵盤觸發(fā)這個(gè)事件。

mouseleave,mouseenter不能冒泡
IE9之后的執(zhí)行順序,IE8及之前會跳過第二個(gè)mousedown和click事件
(1) mousedown
(2) mouseup
(3) click
(4) mousedown
(5) mouseup
(6) click
(7) dblclick

  1. 鍵盤與文本事件
  • keydown:當(dāng)用戶按下鍵盤上的任意鍵時(shí)觸發(fā),而且如果按住不放的話,會重復(fù)觸發(fā)此事件。
  • keypress:當(dāng)用戶按下鍵盤上的字符鍵時(shí)觸發(fā),而且如果按住不放的話,會重復(fù)觸發(fā)此事件。按下Esc鍵也會觸發(fā)這個(gè)事件。Safari 3.1之前的版本也會在用戶按下非字符鍵時(shí)觸發(fā)keypress事件。
  • keyup:當(dāng)用戶釋放鍵盤上的鍵時(shí)觸發(fā)。

5.復(fù)合事件
IE9+支持。

6.變動事件
DOM2級的變動(mutation)事件能在DOM中的某一部分發(fā)生變化時(shí)給出提示。

  • DOMSubtreeModified:在DOM結(jié)構(gòu)中發(fā)生任何變化時(shí)觸發(fā)。這個(gè)事件在其他任何事件觸發(fā)后都會觸發(fā)
  • DOMNodeInserted:在一個(gè)節(jié)點(diǎn)作為子節(jié)點(diǎn)被插入到另一個(gè)節(jié)點(diǎn)中時(shí)觸發(fā)
  • DOMNodeRemoved:在節(jié)點(diǎn)從其父節(jié)點(diǎn)中被移除時(shí)觸發(fā)。
  • DOMNodeInsertedIntoDocument:在一個(gè)節(jié)點(diǎn)被直接插入文檔或通過子樹間接插入文檔之后觸發(fā)。這個(gè)事件在DOMNodeInserted之后觸發(fā)
  • DOMNodeRemovedFromDocument:在一個(gè)節(jié)點(diǎn)被直接從文檔中移除或通過子樹間接從文檔中移除之前觸發(fā)。
  • DOMAttrModified:在特性被修改之后觸發(fā)。
  • DOMCharacterDataModified:在文本節(jié)點(diǎn)的值發(fā)生變化時(shí)觸發(fā)。

7.HTML5事件

  • contextmenu事件
EventUtil.addHandler(window, "contextmenu", function(event){
        var event = EventUtil.getEvent(event);
        event.preventDefault();//禁用鼠標(biāo)默認(rèn)事件,比如右擊
});
  • beforeunload事件
//需要鼠標(biāo)觸發(fā)window對象,即事件的對象。
EventUtil.addHandler(window, "beforeunload", function(event){
    var event = EventUtil.getEvent(event);
    var msg = "你確定要離開嗎?";
    event.returnValue = msg; //事件的返回信息是給用戶的提示信息。
    return msg;
});
  • DOMContentLoaded事件
    如前所述,window的load事件會在頁面中的一切都加載完畢時(shí)觸發(fā),但這個(gè)過程可能會因?yàn)橐虞d的外部資源過多而頗費(fèi)周折。而DOMCon-tentLoaded事件則在形成完整的DOM樹之后就會觸發(fā),不理會圖像、JavaScript文件、CSS文件或其他資源是否已經(jīng)下載完畢。
  • readystatechange事件
    提供與文檔或元素的加載狀態(tài)有關(guān)的信息
  • pageshow和pagehide事件
    第一個(gè)事件就是pageshow,這個(gè)事件在頁面顯示時(shí)觸發(fā),無論該頁面是否來自bfcache。在重新加載的頁面中,pageshow會在load事件觸發(fā)后觸發(fā);而對于bfcache中的頁面,pageshow會在頁面狀態(tài)完全恢復(fù)的那一刻觸發(fā)。另外要注意的是,雖然這個(gè)事件的目標(biāo)是document,但必須將其事件處理程序添加到window。
  • hashchange事件
    監(jiān)聽URL參數(shù)列表變化

8.設(shè)備事件

9.觸摸與手勢事件

五、內(nèi)存與性能
在javascript中,添加到頁面上的事件處理程序數(shù)量將直接關(guān)系到頁面的整體運(yùn)行性能。
原因:
每個(gè)函數(shù)都是對象,都會占用內(nèi)存。
內(nèi)存的對象越多,性能就越差。
事件委托
事件委托利用了事件冒泡,只指定一個(gè)事件,就能管理某一類型的所有事件。

  var btn = document.getElementById("myBtn");
        var handler = function(event){
            switch(event.type){
                case "click":
                    alert("Clicked");
                    break;
                    
                case "mouseover":
                    event.target.style.backgroundColor = "red";
                    break;
                    
                case "mouseout":
                    event.target.style.backgroundColor = "";
                    break;                        
            }
        };
        
        btn.onclick = handler;
        btn.onmouseover = handler;
        btn.onmouseout = handler;

在使用事件時(shí),需要考慮如下一些內(nèi)存與性能方面的問題。

  • 有必要限制一個(gè)頁面中事件處理程序的數(shù)量,數(shù)量太多會導(dǎo)致占用大量內(nèi)存,而且會讓用戶感覺頁面反應(yīng)不夠靈敏。
  • 建立在事件冒泡機(jī)制之上的事件委托技術(shù),可以有效減少事件處理程序的數(shù)量。
  • 建議在瀏覽器卸載頁面之前移除頁面中的所有事件處理程序。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.①DOM2級核心:沒有引入新類型,只是在DOM1級的基礎(chǔ)上通過增加新方法和新屬性來增強(qiáng)了既有類型 ②DOM3級...
    張果果閱讀 298評論 0 0
  • 環(huán)境配置:http://www.itdecent.cn/p/899c1a273a32原文鏈接:http://jav...
    butterflyq閱讀 225評論 0 1
  • 那些再與你無關(guān)的悲傷 大麥茶的清香灌溉著我的眼眶,濕潤的空氣占領(lǐng)了房間里每一處角落,門外嘈雜的敲門聲讓我感到呼吸急...
    步煙素箋閱讀 360評論 2 2
  • Day 8 江晨曦 閱讀 今日閱讀《重新想象學(xué)習(xí)》 接連幾天的燒腦會議,加上超長的工作時(shí)間,感覺大腦已經(jīng)一片混沌了...
    大兒童江晨曦閱讀 625評論 0 0

友情鏈接更多精彩內(nèi)容