摘要:作為事件處理程序的函數一個布爾值。最后這個布爾值為表示在捕獲階段調用事件處理程序,表示在冒泡階段調用事件處理程序。阻止特定事件的默認行為。
事件處理程序 DOM0級事件處理程序
通過Javascript指定事件處理程序的傳統方式,就是將一個函數賦值給一個事件處理程序屬性。
每個元素都有自己的事件處理程序屬性,這些屬性通常全部小寫,例如onclick。將這種屬性的值設置為一個函數,就可以指定事件處理程序。
var btn = document.getElementById("myBtn"); // 添加事件處理程序 btn.onclick = function () { alert( this );//為DOM元素btn }; // 移除事件處理程序 btn.onclick = null;
優點:1.簡單2.具有跨瀏覽器的優勢
缺點:在代碼運行之前不會指定事件處理程序,因此這些代碼在頁面中位于按鈕后面,就有可能在一段時間怎么點擊都沒反應,用戶體驗變差。
定義了兩個方法,用于處理指定和刪除事件處理程序的操作:addEventListener()和removeEventListener()。三個參數,1.要處理的事件名。2.作為事件處理程序的函數3.一個布爾值。最后這個布爾值為true,表示在捕獲階段調用事件處理程序,false表示在冒泡階段調用事件處理程序。
// 添加多個事件處理程序 var btn = document.getElementById("myBtn"); btn.addEventListener("click",function (){ alert( this );// 為DOM元素btn },false ); btn.addEventListener("click",function () { alert("Hello World"); },false); // 移除事件處理程序 btn.removeEventListener("click",function () { // 匿名函數無法被移除,移除失敗 },false); // 改寫 var handler = function () { alert(this.id); }; btn.addEventListener("click",handler,false); // 再次移除事件處理程序 btn.removeEventListener("click",handler,false);// 移除成功
這兩個事件處理程序會按照添加他們的順序觸發。大多數情況,都是將事件處理程序添加到事件流的冒泡階段,這樣可以最大限度的兼容各種版本的瀏覽器。
優點: 一個元素可以添加多個事件處理程序
缺點: IE8及以下瀏覽器不支持DOM2級事件處理程序。(包括IE8)
定義了兩個方法,與上類似:attachEvent(),detachEvent()。這兩個方法接收相同的兩個參數:事件處理程序名稱和事件處理程序函數。由于IE8以及更早版本的瀏覽器只支持事件冒泡,所以通過detachEvent()添加的事件處理程序會被添加到冒泡階段。
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function(){ alert( this );// window }); btn.attachEvent("onclick", funciton(){ alert("HELLO, WORLD"); });
點擊按鈕,這兩個事件處理程序的觸發順序與上述剛好相反。不是按照添加事件處理程序的順序觸發,剛好相反。
優點:一個元素可以添加多個事件處理程序
缺點:只支持IE。
var EventUtil = { addHandler : function ( ele, type, handler ) { if ( ele.addEventListener ) { ele.addEventListener( type, handler, false ); } else if ( ele.attachEvent ) { ele.attachEvent( "on" + type, handler ); } else { ele["on" + type] = handler } }, removeHandler: function ( ele, type, handler ) { if ( ele.removeEventListener ) { ele.removeEventListener( type, handler, false ); } else if ( ele.detachEvent ) { ele.detachEvent( "on" + type, handler ); } else { ele[ "on" + type ] = null; } } }事件對象 DOM中的事件對象
兼容DOM的瀏覽器會將一個event對象傳入到事件處理程序中。無論指定事件處理程序時使用什么方法(DOM0級或DOM2)級,都會傳入event對象。event對象包含與創建它的特定事件有關的屬性和方法。觸發的事件類型不一樣,可用的屬性和方法也不一樣。不過,所有事件都有下表列出的成員
| 屬性/方法 | 類型 | 說明
| ---------—--- | ------------- | ------------
| bubbles
| cancebles
| currentTarget
| defaultPrevented
| detail
| evnetPhase
| preventDefault
| stopImmediatePropagation()
| stopPropagation()
| target
| trusted
| type
| view
1.currentTarget與target
target :事件的目標對象
currenTarget : 其當前事件處理程序正在處理事件的那個元素
var btn = document.getElementById("myBtn"); btn.onclick = function ( e ) { console.log( this === e.currentTarget );// true console.log( this === e.target );// true }; document.body.onclick = function ( e ) { console.log( this === e.currentTarget );// true console.log( this === e.target );// false };
點擊按鈕,結果如上。
2.preventDefault()與cancelable
cancelable :只讀屬性,表明是否可以取消事件的默認行為,值為true便可以,反之不行。
preventDefault :阻止特定事件的默認行為。例如,鏈接的默認行為就是在被單擊時會導航到其href特性指定的URL。
var link = document.getElementById( "myLink" ); link.onclick = function ( e ) { // 阻止默認行為 e.preventDefault();// 只有cancelable設置為true的事件,才可以使用 }
3.stopPropagation()與eventPhase
stopPropagation() : 取消事件進一步捕獲或冒泡,如果bubbles為true,則可以使用這個方法
eventPhase : 調用事件處理程序的階段:1.表示捕獲階段2.表示"處于目標階段"3.表示冒泡階段。
var btn = document.getElementById("myBtn"); document.body.addEventListener( "click", function ( e ) { alert( e.eventPhase ); }, true );// 1 btn.addEventListener( "click",function ( e ) { alert( e.eventPhase ); }, false );// 2 document.body.addEventListener( "click", function ( e ) { alert( e.eventPhase ); }, false );// 3
點擊btn按鈕彈出1,2,3。
var btn = document.getElementById("myBtn"); document.body.addEventListener( "click", function ( e ) { alert( e.eventPhase );// 1 }, true ); btn.addEventListener( "click",function ( e ) { // 阻止進一步的事件冒泡 e.stopPropagation(); alert( e.eventPhase );// 2 }, false ); document.body.addEventListener( "click", function ( e ) { alert( e.eventPhase );// 點擊按鈕時,事件處理程序被阻止,無反應 }, false );
點擊btn按鈕彈出1,2。
var btn = document.getElementById("myBtn"); document.body.addEventListener( "click", function ( e ) { // 阻止進一步的事件冒泡 e.stopPropagation(); alert( e.eventPhase );// 1 }, true ); btn.addEventListener( "click",function ( e ) { alert( e.eventPhase );// 點擊按鈕時,事件處理程序被阻止,無反應 }, false ); document.body.addEventListener( "click", function ( e ) { alert( e.eventPhase );// 點擊按鈕時,事件處理程序被阻止,無反應 }, false );
點擊btn按鈕彈出1。
IE中的事件對象訪問IE中的event對象有幾種不同的方式,取決于指定事件處理程序的方法。IE的event對象同樣也包含與創建它的事件相關的屬性和方法。與DOM中的event對象一樣,這些屬性和方法也會因為事件類型的不同而不同,但所有事件對象都會包含下表所列的屬性和方法。
| 屬性/方法 | 類型 | 說明
| ---------—--- | ------------- | ------------
| cancelBubble
| returnValue
| srcElement
| type
1.srcElement
事件的目標(與DOM中的target屬性相同)
var btn = document.getElementById("myBtn"); btn.onclick = function () { alert( window.event.srcElement === this )// true }; btn.attachEvent("onclick", function (e) { alert( e.srcElement === this ) // false, IE事件處理程序綁定this的值為window });
2.returnValue
默認值為true,但將其設置為false就可以取消事件的默認行為(與DOM中的preventDefault()作用相同)
var link = document.getElementById( "myLink" ); link.onclick = function () { // 阻止默認行為 window.event.returnValue = false; }
與DOM不同的是,在此沒有辦法確定事件是否能被取消。
3.cancelBubble
默認值為false,但將其設置為true就可以取消事件冒泡(與DOM中的stopPropagation()作用相同)
var btn = document.getElementById("myBtn"); btn.onclick = function () { alert( "Clicked" ); window.event.cancelBubble = true; }; document.body.onclick = function () { alert( "Body Clicked" ) };跨瀏覽器的事件對象
要訪問IE中event對象有幾種不同的方式,取決于指定事件處理程序的方法。在使用DOM0級方法添加事件處理程序時,event對象作為window對象的一個屬性存在。使用IE事件處理程序,event對象可以通過window對象進行訪問,同時也會被當做參數傳遞。
var EventUtil = { getEvent: function( event ){ return event ? event : window.event } }事件類型
HTML5事件DOM3級事件模塊在DOM2級事件模塊基礎上重新定義了這些事件,也添加了一些新事件。包括IE9在內的所有主流瀏覽器都支持DOM2級事件。IE9也支持DOM3級事件。
DOMContentLoaded :
可以為document和window添加相應的事件處理程序(盡管這個事件會冒泡到window,但它的目標實際上是document)。
DOMContentLoaded中的event對象不會提供額外的信息(其target屬性是document)
兼容性:IE9+,Fifrefox,Chrome,Safari3.1+,Opera9+。
hashchange :
必須要把hashchange事件處理程添加給window對象,然后URL參數列表只要變化就會調用它。
此時的event對象應該額外包含兩個屬性:oldURL和newURL。這兩個屬性分別保存著參數列表變化前后的完整URL。
兼容性:IE8+,firefox3.6+,Safari5+,Chrome,Opera10.6+。在這些瀏覽器中只有Firefox6+,chrome和Opera支持oldURL和newURL屬性。為此,最好是使用location對象來確定當前的參數列表。
keydown(任意鍵),keypress(字符鍵), keyup
發生keypress事件意味著按下的鍵會影響到屏幕中文本的顯示。在所有瀏覽器中,按下能夠插入或者刪除字符的鍵都會觸發keypress事件。
所有元素都支持以上三個事件,但只有在用戶通過文本框輸入文本時才最常用到
觸發順序:在用戶按下了一個字符鍵時,keydown-->keypress-->keyup。在用戶按下的是一個非字符鍵,keydown-->keyup。
event對象
shiftKey,ctrlKey,altKey和metaKey屬性。
在發生keydown和keyup事件時,event對象的keyCode屬性會包含一個鍵碼。
兼容性:IE不支持metaKey
Working With the Keyboard
mousedown,mouseup
click,dbclick
所有元素都支持鼠標事件。
觸發順序:mousedown-->mouseup-->click-->mousedown-->mouseup-->click--dbclick。在IE8以及之前版本,有一個小bug,會跳過第二個mousedown和click
event對象:
clientX和clientY:表示事件發生時,鼠標指針在視口中的水平和垂直坐標
PageX和PageY:表示鼠標光標在頁面中的位置,因此坐標是從頁面本身,而非視口的左邊和頂邊計算的。
screenX和screenY:可以確定鼠標事件發生時,鼠標指針相對于整個屏幕的坐標信息。
shiftKey,ctrlKey,altKey和metaKey屬性。
mousedown和mouseup事件,還包括一個button屬性:表示按下或釋放的按鈕DOM的button屬性可能有如下3個值,0表示主鼠標按鈕,1表示中間的鼠標按鈕,2表示次鼠標按鈕。
兼容性:
IE8以及更早版本不支持事件對象上的頁面坐標,不過使用客戶區坐標和滾動信息可以計算出來。
IE8以及更早版本不支持metaKey屬性。
touchstart
內存和性能 事件處理程序對性能的影響在javascript中,添加到頁面上的事件處理程序數量將直接關系到頁面的整體運行性能。
1.每個函數(事件處理程序)都是對象,都會占用內存。內存中的對象越多,性能就越差。
2.必須事先指定所有 事件處理程序而導致的DOM訪問次數,會延遲整個頁面的交互就緒時間。
3.每當將 事件處理程序指定給元素時,運行中的瀏覽器代碼與支持頁面交互的Javascript代碼之間就會建立一個連接。這種連接越多,頁面執行起來越慢。
var l = document.getElementById( "love-l" ); var o = document.getElementById( "love-o" ); var v = document.getElementById( "love-v" ); var e = document.getElementById( "love-e" ); l.addEventListener("click", function () { alert(" L ") }, false); o.addEventListener("click", function () { alert( "O" ) }, false); v.addEventListener("click", function () { alert( "V" ) }, false); e.addEventListener("click", function () { alert( "E" ) }, false);LOVE
在上面的示例中,為每個元素的點擊事件都綁定了不同事件處理程序。
取得了4個DOM元素。==>DOM訪問次數為4次
添加了4個事件處里程序。==>內存中的對象多增加了4個
相應的事件處理程序與指定元素連接了4次==》連接數4
如果頁面復雜,那么就會有數不清的代碼用于添加事件處理程序。影響頁面性能。
事件委托對事件處理程序過多問題的解決方案就是事件委托。
事件委托利用了事件冒泡,只指定一個事件處理程序,就可以管理 某一類型(例如:點擊事件)的所有事件。
如果可行的話,可以考慮為document對象添加一個事件處理程序,用以處理頁面上特定類型的事件。有點如下
document對象很快就可以訪問,而且可以在頁面生命周期中的任何時點上為它添加事件處理程序(無需等待load和DOMContentLoaded事件)。換句話說,只要可點擊的元素呈現在頁面上,就可以立即具備適當的功能
在頁面中設置事件處理程序所需的時間更少。只添加一個事件處理程序所需的DOM引用更少,所花的時間更少。 整個頁面所占得內存空間更少
var love = document.getElementById( "love-wrapper" ); love.addEventListener("click", function ( e ) { switch ( e.target.id ) { case "love-l" : alert("L"); break; case "love-o" : alert("O"); break; case "love-v" : alert("V"); break; case "love-e" : alert("E"); break; } },false)
在上面的示例中
取得了1個DOM元素。==>DOM訪問次數減少到了1次
添加了1個事件處理程序。==>內存中的對象只增加了1個
相應的事件處理程序與指定元素連接了4次==>連接數1
實現了和上一個例子中一樣的效果。但是卻有效的控制了DOM訪問次數,事件處理程序的添加個數,以及DOM元素與相應的事件處理程序的連接次數。
移除事件處理程序利用事件委托我們可以有效的控制相應的事件處理程序與指定元素的連接次數。另外,在不需要的時候移除事件處理程序,也是解決這個問題的一種方案。內存中留有那些過時不用的"空事件處理程序,也是造成Web應用程序內存和性能問題的主要原因"。
有兩種情況可能導致上述問題
帶有事件處理程序的 指定元素 通過DOM操作被刪除了,頁面中的某一部分被替換了,導致帶有事件處理程序的 指定元素 被刪除了。
卸載頁面的時候。
第一種情況:本質上來講都是一種情況,就是帶有事件處理程序的 指定元素被刪除了,但是其事件處理程序仍然和 指定元素保持著引用關系,導致其事件處理程序無法被當做垃圾回收。(尤其是IE)會做出這種處理
var handler = function () { // 刪除指定元素 document.getElementById( "myDiv" ).removeChild(); } var btn = document.getElementById("myBtn"); btn.addEventListener("click", handler, false);
點擊按鈕時,按鈕被刪除,但是其事件處理程序卻還和其保持了引用關系,導致內存增加。因此在知道 指定元素可能被刪除的情況下,先解除他們之間的引用關系。如下
var handler = function () { // 解除連接引用關系 btn.removeEventListener( "click", handler, false ); // 刪除指定元素 document.getElementById( "myDiv" ).removeChild(); } var btn = document.getElementById("myBtn"); btn.addEventListener("click", handler, false);
這樣通過解除引用連接關系,也可以提升頁面性能。
第二種情況:IE8及更早瀏覽器在這種情況下仍然是問題最多的瀏覽器。如果在頁面卸載之前,沒有清理干凈事件處理程序,那它們就會滯留在事件處理程序中。
一般來說,最好的做法是在頁面卸載之前,先通過unload事件處理程序移除所有事件處理程序。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78645.html
摘要:標準庫中的所有方法都提供非阻塞的異步版本,并接受回調函數,某些方法還具有對應的阻塞方法,其名稱以結尾。比較代碼阻塞方法同步執行,非阻塞方法異步執行。 阻塞與非阻塞概述 此概述介紹了Node.js中阻塞與非阻塞調用之間的區別,此概述將引用事件循環和libuv,但不需要事先了解這些主題,假設讀者對JavaScript語言和Node.js回調模式有基本的了解。 I/O主要指與libuv支持的...
摘要:調用棧是單線程編程語言,意味著它只有單一的調用棧。調用棧是一種數據結構,基本記錄了程序運行的位置。舉個例子,先來看如下所示的代碼當引擎開始執行這段代碼時,調用棧將是空的。這正是拋出異常時棧追蹤的構造過程這基本上就是異常拋出時調用棧的狀態。 原文 How JavaScript works: an overview of the engine, the runtime, and the c...
摘要:調用棧是一種數據結構,它記錄了我們在程序中的位置。當從這個函數返回的時候,就會將這個函數從棧頂彈出,這就是調用棧做的事情。而且這不是唯一的問題,一旦你的瀏覽器開始處理調用棧中的眾多任務,它可能會停止響應相當長一段時間。 原文地址: https://blog.sessionstack.com... PS: 好久沒寫東西了,最近一直在準備寫一個自己的博客,最后一些技術方向已經敲定了,又可以...
摘要:調用棧是一種單線程編程語言,這意味著它只有一個調用堆棧。調用棧是一種數據結構,它記錄了我們在程序中的位置。而且這不是唯一的問題,一旦你的瀏覽器開始處理調用棧中的眾多任務,它可能會停止響應相當長一段時間。 本文是旨在深入研究JavaScript及其實際工作原理的系列文章中的第一篇:我們認為通過了解JavaScript的構建塊以及它們是如何工作的,將能夠編寫更好的代碼和應用程序。我們還將分...
摘要:是如何工作的引擎,運行時以及調用棧的概述原文譯者隨著變得越來越流行,團隊在多個層級都對它進行利用前端,后端,混合應用,嵌入式設備以及更多。這個將會在是如何工作的的第二部分進一步解釋。 How JavaScript works: an overview of the engine, the runtime, and the call stack JavaScript是如何工作的:引擎,運...
摘要:如果我們進入一個函數,我們在堆棧的頂部。看看下面的代碼當引擎開始執行此代碼時,調用堆棧將為空。之后,步驟如下調用堆棧中的每個條目稱為堆棧幀。這正是拋出異常時構造堆棧跟蹤的方式當異常發生時,它基本上是調用堆棧的狀態。 隨著JavaScript越來越受歡迎,團隊正在利用這個技術棧在多個層次- 前端,后端,混合應用程序,嵌入式設備等等提供支持。 這篇文章旨在成為系列中第一個旨在深入挖掘Jav...
閱讀 2003·2021-11-23 10:08
閱讀 2336·2021-11-22 15:25
閱讀 3275·2021-11-11 16:55
閱讀 771·2021-11-04 16:05
閱讀 2600·2021-09-10 10:51
閱讀 711·2019-08-29 15:38
閱讀 1582·2019-08-29 14:11
閱讀 3486·2019-08-29 12:42