事件流。 事件冒泡; 事件捕獲; 事件對象; 事件處理程式; 等
由處理程式來監聽某個動作,一旦某個動作發生,那麼處理程式就作出響應,這就是觀察者模式的簡單案例。在JavaScript中,按鈕一旦被點擊(或者其他動作,拿點擊按鈕舉例),就會有響應的處理程式進行響應,比如,點擊按鈕彈出一個對話框、滑鼠滑過按鈕會提示一行字等等,這就是JavaScript中要講的事件,也屬於經典的觀察者模式。
- 事件流。
在DOM樹中,可能一個<button>元素屬於一個<div>元素的子元素,而<div>又屬於<html>的子元素。這個時候,點擊<button>這個元素,<button>就會觸發一個事件(或者一個動作),而<div>、<html>有可能也要接收到這個事件的信號。也就是說,你打了button一下,它的父親、祖父都會感受到你的打擊。這就是事件流。IE的事件流是事件冒泡流。
- 事件冒泡
- IE的事件流叫做事件冒泡。即事件從最深的元素開始接收,然後逐級向上傳播。
如:打了孫子一下,孫子感受到疼,然後父親感知,最後爺爺感知,追本溯源,直到老祖宗感知。
- 事件冒泡的過程圖:
- 、
- IE的事件流叫做事件冒泡。即事件從最深的元素開始接收,然後逐級向上傳播。
- 事件捕獲
- 事件捕獲與事件冒泡正好相反,即從最外層開始接收事件,直到最深的元素。
罵了姓張的人,首先張姓的祖宗感到恥辱,接著張姓的爺爺、爸爸、自己分別感受到。
- 事件捕獲很少用到。過程圖與事件冒泡相反。
- 事件捕獲與事件冒泡正好相反,即從最外層開始接收事件,直到最深的元素。
- DOM的事件流
- DOM2級事件包括三個階段:事件捕獲階段、處理目標階段、事件冒泡階段。
先發生事件捕獲,傳遞到最深一層,由具體元素接收到事件,然後冒泡並處理程式。(下麵講到第10節事件對象的target屬性時會具體解釋這一現象)
- 過程圖:
- DOM2級事件包括三個階段:事件捕獲階段、處理目標階段、事件冒泡階段。
- 事件處理程式
- 事件就是用戶或者瀏覽器自身執行的某種動作。而響應某個事件的函數就叫做事件處理程式。
諸如click、load、mouseover都是事件的名字。 事件處理程式的名字則在前面加on,比如:onclick、onload等。
-
示例:
1 <body> 2 <input type="button" value="Click Me" onclick="alert('Clicked')" /> 3 <!--雙引號轉義--> 4 <input type="button" value="Click Me" onclick="alert("Clicked")" /> 5 6 <script type="text/javascript"> 7 function showMessage(){ 8 alert("Hello world!"); 9 } 10 </script> 11 <input type="button" value="Click Me" onclick="showMessage()" /> 12 <!--防止在函數未載入時點擊--> 13 <input type="button" value="Click Me" onclick="try{showMessage();}catch(ex){}" /> 14 </body>
<input>是元素, onclick是事件處理程式的名字,跟value、type一樣,是屬性。
-
缺點:
- 如果<input>寫在<script>上方,函數尚未載入時,用戶可能就點擊元素,導致報錯。所以上面代碼13行進行try catch捕獲。
- 如果要修改事件函數,那麼<input>里的onclick和<script>里的具體函數都要修改,HTML與JavaScript太緊密耦合。
- 事件就是用戶或者瀏覽器自身執行的某種動作。而響應某個事件的函數就叫做事件處理程式。
- DOM0級事件處理程式
- 在JavaScript中,取出要觸發的元素,把函數賦值給事件處理程式屬性。
1 <body> 2 <input type="button" id="myBtn" value="Click Me" /> 3 <input type="button" id="myRemoveBtn" value="Remove Event Handler" /> 4 <script type="text/javascript"> 5 var btn = document.getElementById("myBtn"); 6 //會在事件流的冒泡階段處理 7 btn.onclick = function(){ 8 alert(this.id);//this指示當前元素 9 }; 10 11 var removeBtn = document.getElementById("myRemoveBtn"); 12 removeBtn.onclick = function(){ 13 btn.onclick = null;//刪除事件處理程式 14 }; 15 </script> 16 </body>
- 在JavaScript中,取出要觸發的元素,把函數賦值給事件處理程式屬性。
- DOM2級事件處理程式
IE9及其他主流瀏覽器支持DOM2級事件處理程式。
- DOM2級事件給元素定義了兩個方法:
- 指定事件處理程式的操作:addEventListener();
- 刪除事件處理程式的操作:removeEventListener();
- DOM2級之於DOM1級最大的優勢在於,可以註冊多個事件。
比如點擊某個按鈕,要彈出一個提示框,同時要按鈕改變顏色,這時就需要同時添加兩個事件處理程式。
- 示例:
<body> <input type="button" id="myBtn" value="Click Me" /> <p>This example won't work in Internet Explorer.</p> <script type="text/javascript"> var btn = document.getElementById("myBtn"); btn.addEventListener("click", function(){ alert(this.id); }, false); /**第三個參數預設為false,表示在冒泡階段觸發。如果為true,表示在捕獲階段觸發,true一般不會用*/ btn.addEventListener("click", function(){ alert("Hello world!"); }, false); </script> </body>
- DOM2級事件給元素定義了兩個方法:
- IE事件處理程式
- IE事件給元素定義了兩個方法:
- 指定事件處理程式的操作:attachEvent();
- 刪除事件處理程式的操作:detachEvent();
- attachEvent()與DOM0級註冊事件在作用域上有不同。
- DOM0級:作用域是所屬元素。
即:如果在函數中使用this,this指示當前元素
- attachEvent():作用域是全局作用域(即window)。
- DOM0級:作用域是所屬元素。
- 添加多個事件處理程式,按相反的順序觸發。
- IE事件給元素定義了兩個方法:
- 跨瀏覽器的事件處理程式
- 為保持相容,可以寫一個公共事件Util。下麵是Util中的添加事件示例:
addHandler: function(element, type, handler){ if (element.addEventListener){ element.addEventListener(type, handler, false); } else if (element.attachEvent){ element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } }
- 為保持相容,可以寫一個公共事件Util。下麵是Util中的添加事件示例:
- 事件對象
- 在觸發DOM上的某個事件時,會在方法中傳入一個事件對象event(隱藏),這個對象中包含著所有與事件相關的信息。下麵列舉部分event的屬性:
- currentTarget:當前正在處理事件的那個元素。
- target:事件的目標。
在事件處理程式內部,對象this始終等於currentTarget的值,
而target則只包含事件的實際目標。
一般情況下,currentTarget都與target相等。
但是,假如<button>的父元素是<div>,你給<div>元素綁定了一個onclick,
那麼這時,<div>元素是currentTarget值,而target是最終目標:<button>(向下捕獲)。
由於按鈕<button>上並未綁定onclick事件處理程式,
結果click事件就冒泡到了<div>,在那裡事件得到處理。
- IE中的事件對象
IE中的事件對象與其他主流瀏覽器稍微不同,比如,使用DOM0級方法添加事件處理程式時,方法中傳入的event對象是window對象的一個屬性,event事件對象的目標對象屬性為srcElement而非target等等。所以一般情況下會寫一個跨瀏覽器的Util。
- 在觸發DOM上的某個事件時,會在方法中傳入一個事件對象event(隱藏),這個對象中包含著所有與事件相關的信息。下麵列舉部分event的屬性:
- 事件類型
- 上述舉例最多的是onclick事件類型,實際上,事件類型多種多樣,如:
- UI事件:用戶與界面交互時觸發。
- 焦點事件:元素獲得或者失去焦點時。
- 滑鼠事件:單擊、雙擊、右擊等。
- 滾輪事件:滑鼠滑輪滾動時。
- 鍵盤事件:鍵盤上按下某個鍵時。
- 等等。
- javascript中最常用的事件就是load,頁面全部載入後,就會觸發load事件。
- 圖像上面也可以觸發load事件,當圖像載入完畢時可以指定事件。
- 用戶從一個頁面切換到另一個頁面,會觸發unload事件。
- 當瀏覽器視窗大小被調整後,會觸發resize事件。
- 鍵盤事件也經常用到。
- keydown:用戶按下鍵盤上的任意鍵時觸發。按住不放會重覆觸發。
- keyup:用戶釋放鍵盤上的鍵時觸發。
- 在發生keydown或者keyup時,event對象的keyCode屬性會包含一個數字,與鍵盤上的一個特定的鍵對應。(比如:回車:13;退出:27;左箭頭:37;等等)。
- 使用回車鍵觸發事件舉例:
<meta http-equiv="content-type" content="text/html; charset=gb2312"/> <script type="text/javascript"> function show () { //火狐不支持window.event,所以加入"或"條件 var e=window.event||arguments.callee.caller.arguments[0]; if(e.keyCode==13){ alert("你按下了回車"); } } </script> <input onkeydown="show();" value="觸發鍵盤試試">
- 上述舉例最多的是onclick事件類型,實際上,事件類型多種多樣,如:
- 記憶體和性能
在javascript中,添加到頁面上的事件處理程式數量將直接影響到頁面整體的運行性能。 每個函數都是對象,都會占用記憶體。 記憶體中的對象越多,性能就越差。 所以要利用好事件處理程式,比如使用事件委托等。