摘要:指定事件處理程序指定事件處理程序主要有兩種方式級事件處理程序級事件處理程序。添加事件處理程序注意這里是哦或移除事件處理程序使用移除事件處理程序的條件與方法相同必須提供相同的參數,從而添加的匿名函數也無法被移除。
今天看書又看到事件,遂決定小總結一下~
JavaScript與HTML之間的交互是通過事件實現的。事件,就是文檔或瀏覽器窗口中發生的一些特定的交互瞬間。可以使用監聽器(事件處理程序)來監聽事件,以便事件發生時執行相應的代碼。
本文主要講事件流和事件處理程序。后續會再寫一篇文章,總結事件類型。
大家都舉同心圓的栗子,我在這里也說說咯~想象畫在一張紙上的一組同心圓,如果把手指放在圓心上,那么手指碰觸的不是一個圓,而是紙上所有的圓。這和點擊HTML頁面上的元素原理是一樣的,如果頁面上有個按鈕,你點擊按鈕的同時,也點擊了按鈕的容器元素,點擊了容器元素的容器元素……點擊了整個頁面。
事件流描述的是從頁面中接收事件的順序。現存兩種事件流:
事件冒泡流——IE
事件捕獲流——Netscape
事件冒泡接收事件的順序是:事件由最具體的元素接收,逐級向上傳播到較為不具體的節點。
如果頁面中有個div,點擊了div之后,事件的傳播順序如下:
(1) div
(2) body
(3) html
(4) document
事件冒泡的過程如下圖:
所有現代瀏覽器都支持事件冒泡,而且IE9,Firefox、Chrome、Safari都將事件一直冒泡到window對象。
事件捕獲接收事件的順序是:事件由最不具體的元素接收,逐級向下傳播到最具體的節點。
如果頁面中有個div,點擊了div之后,事件的傳播順序如下:
(1) document
(2) html
(3) body
(4) div
事件捕獲的過程如下圖:
IE9,Firefox、Chrome、Safari都支持這種事件流模型,而且是從window對象開始捕獲事件的。
DOM事件流“DOM2級事件”規定事件流包含3個階段:事件捕獲階段、處于目標階段、事件冒泡階段。
如下圖:
在DOM事件流中,捕獲階段包括1,2,3。冒泡階段包括4,5,6,7。其中4是處理目標階段,在事件處理中被看成是冒泡階段的一部分。
雖然“DOM級事件”規范明確規定捕獲階段不涉及事件目標,但是IE9,Firefox、Chrome、Safari和Opera9.5及以上版本都會在捕獲階段觸發事件對象上的事件,這就意味著有兩個機會在目標對象上面操作事件。
IE9,Firefox、Chrome、Safari、Opera都支持DOM事件流,IE8及更早版本不支持DOM事件流。即IE9,Firefox、Chrome、Safari、Opera及支持冒泡又支持捕獲,而IE8及以前版本僅支持冒泡。
需要說明的是,在實際中,大多數都使用冒泡事件,僅在有特殊需要時才使用捕獲事件。
事件處理程序在說事件處理程序之前,先簡單介紹下事件對象。什么是事件對象呢?
在觸發DOM上的某個事件時,會產生一個對象,這個對象中包含所有與事件有關的信息,如導致事件的元素、事件的類型以及其他與特定事件相關的信息,這個對象就是事件對象。所有的事件處理程序都可以訪問事件對象,但是訪問的方式不盡相同,一種是將事件對象作為事件處理程序的參數,另一種是事件對象作為window的屬性,通過window.event來訪問。這里就介紹到這里,先有個概念~
回歸正題,click,load,mouseover都是事件的名字,而響應某個事件的函數就叫做事件處理程序,事件處理程序的名字以“on”開頭。
那么該怎樣為事件指定處理程序呢?主要有兩類方法:HTML事件處理程序和JavaScript指定事件處理程序。
HTML特性指定事件處理程序某個HTML元素支持的每種事件,都可以使用一個與相應事件處理程序同名的HTML特性來指定。這個特性的值是能夠執行的JavaScript代碼。
具體指定方式或
這種方式中,事件處理程序中的代碼在執行時,有權訪問全局作用域中的任何代碼。
本質這樣的事件處理程序在執行的時候,會創建一個封裝著元素屬性值的函數,然后執行這個函數。就是說,
當單擊按鈕的時候,先創建一個函數function () { console.log("hello"); },然后立即執行該函數。
這個函數有以下3個特點:
1) 函數中會有一個局部變量event,即事件對象。
注意:event是局部變量,可以在函數中直接訪問,既不用自己定義,也不是從參數列表中讀取。這點與后面其他指定事件處理程序的方式有所不同,記得區分。
2) 函數內部,this值等于事件的目標元素。
3)這個動態創建的函數使用with擴展作用域:
function () { with(document) { with(this) { // 元素屬性值,如 console.log("hello"); } } }
從而該函數可以訪問document及該元素本身的任何成員。這也是為什么“采用這種方式指定的事件處理程序中的代碼在執行時,有權訪問全局作用域中的任何代碼。”,因為作用域中有document。
取消事件默認行為的方法實質上就是讓動態創建的函數return false,所以要這樣寫:
baidu
或
baidu
第二種方式一定要注意,return false是加在onclick屬性值里面的,如果放到show()里是不起作用的哦,因為是要“讓動態創建的函數return false”
3個缺點時差問題
用戶可能會在HTML元素一出現就在頁面上觸發相應的事件,但當時的事件處理程序有可能尚不具備執行的條件,從而引發錯誤。比如上面的show()函數,如果用戶單擊按鈕的時候,function show(){}還沒有執行,就會導致錯誤。
這樣擴展事件處理程序的作用域鏈在不同的瀏覽器中會導致不同的結果。
HTML與JavaScript代碼緊密耦合,所以實際中這種方法使用的比較少。
JavaScript指定事件處理程序JavaScript指定事件處理程序主要有兩種方式:DOM0 級事件處理程序、DOM2 級事件處理程序。使用JavaScript指定事件處理程序,首先必須取得對一個操作對象的引用。
DOM0 級事件處理程序每個元素(包括window和document)都有自己的事件處理程序屬性,這些屬性通常全部小寫,如onclick,將這種屬性賦值為一個函數,就是DOM0 級事件處理程序的指定方式。如下:
var btn = document.getElementById("myBtn"); // 取得對操作對象的引用 btn.onclick = function () { // 為onclick賦值一個函數,指定事件處理程序 console.log("hello"); }移除事件處理程序:
btn.onclick = null; // 只需將屬性置空特點:
1)添加事件處理程序的代碼只有在運行完之后才會為元素綁定事件處理程序,因此如果該段代碼未執行單擊按鈕是沒有反應的。
2)事件處理程序中的this引用當前元素,即綁定了該事件的元素。
3)以這種方式添加的事件處理程序會在事件流的冒泡階段被處理。
4)所有的瀏覽器都支持DOM0 級事件處理程序。
“DOM2 級事件處理程序”定義了兩個方法,用來指定和刪除事件處理程序:addEventListener() 和 removeEventListener()。這兩個方法都接受3個參數:要處理的事件名、作為事件處理程序的函數、一個布爾值,這個布爾值參數如果為true表示在捕獲階段調用事件處理程序,為false表示在冒泡階段調用事件處理程序,一般設為false。
添加事件處理程序:var btn = document.getElementById("myBtn"); // 取得對操作對象的引用 btn.addEventListener("click", function(){ // 注意是 click 哦~ console.log("hello"); }, false);
或
function show() { console.log("hello"); } var btn = document.getElementById("myBtn"); // 取得對操作對象的引用 btn.addEventListener("click", show, false);移除事件處理程序:
移除事件處理程序有一個要求就是:移除時傳入的參數必須與添加事件處理程序時使用相同的參數。從而通過addEventListener()添加的匿名函數將無法移除。
移除上面第二種方式綁定的事件處理程序代碼:
var btn = document.getElementById("myBtn"); // 取得對操作對象的引用 btn.removeEventListener("click", show, false);
要說明的是:通過addEventListener添加的事件處理程序只能通過removeEventListener()來移除。
特點1)只有運行完addEventListener()才為元素綁定了事件處理程序。
2)事件處理程序中的this引用當前元素,即綁定了該事件的元素。
3)通過設置第三個參數為true或false可以設定在捕獲階段還是冒泡階段調用事件處理程序。
4)可以為同一個元素綁定多個事件處理程序,綁定的事件處理程序會按照它們添加的先后順序依次觸發。這是DOM0 級事件處理程序不支持的哦~ DOM0 級只能添加一個事件處理程序,后添加的會覆蓋先添加的。
5)IE9、Firefox、Safari、Chrome和Opera都支持DOM2 級事件處理程序。
上面特地加粗了IE9,那么IE8及以前版本怎么辦呢?IE實現了與DOM中類似的兩個方法:attachEvent()和detachEvent()。這兩個方法僅接受兩個參數:事件處理程序名稱和事件處理程序函數。IE8及之前版本僅支持事件冒泡,所以通過attachEvent()添加的事件處理程序會在冒泡階段調用。
注:IE10及之前版本支持attachEvent()和detachEvent()方法,IE11不再支持,一般IE9及以上都使用DOM方法,這兩個方法僅對IE8及以下版本使用。
添加事件處理程序:var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", function () { // 注意這里是 onclick 哦~ console.log("hello"); });
或
function show() { console.log("hello"); } var btn = document.getElementById("myBtn"); btn.attachEvent("onclick", show);移除事件處理程序:
使用detachEvent移除事件處理程序的條件與DOM方法相同——必須提供相同的參數,從而添加的匿名函數也無法被移除。
var btn = document.getElementById("myBtn"); btn.detachEvent("onclick", show);
1)只有運行完attachEvent()才為元素綁定了事件處理程序。
2)事件處理程序會在全局作用域中運行,從而事件處理程序中的this指向全局對象window。這與之前的都不同哦~所以不能認為this始終等于事件目標,當使用attachEvent()的時候,this是window,不過其他時候,this是等于事件目標的~
3)可以為同一個元素綁定多個事件處理程序,綁定的事件處理程序會按照它們添加順序的相反次序被觸發,即先添加后執行,后添加的先執行。
是不是覺得IE太奇葩呢,如果沒有IE,前端世界會和諧很多吧~還好IE9以上都是按照DOM標準來了,不再我行我素。
事件對象event這里順便簡單說下事件對象,對比來看,會更清晰~
前面介紹過事件對象,這里不再贅述。
HTML特性指定事件處理程序
事件處理程序中會有個局部變量event,這個event就是事件對象。
JavaScript指定事件處理程序
無論指定事件處理程序采用的是DOM0 級還是DOM2 級方法,事件對象都會作為事件處理程序的參數傳入到事件處理程序中。
奇葩的IE
在使用DOM0 級方法添加事件處理程序時,事件對象作為window對象的屬性存在,通過window.event訪問。
如果使用attachEvent()添加事件處理程序,事件對象會作為參數傳入到事件處理程序中。
DOM中的事件對象(兩個方法)
preventDefault()方法用來取消事件默認行為,stopPropagation()方法用來阻止事件進一步捕獲或冒泡
// 假設事件對象傳入給參數event event.preventDefault(); // 取消事件默認行為 event.stopPropagation(); // 阻止事件進一步捕獲或冒泡
IE8及以下中的事件對象(兩個屬性)
returnValue屬性用來設置事件的默認行為。默認值為true,當設置為false時,就會取消事件的默認行為。
cancelBubble屬性用來取消事件冒泡。默認值為false,當設置為true時,就會阻止事件冒泡。
event.returnValue = false; // 取消事件的默認行為 event.cancelBubble = true; // 阻止事件冒泡
注:這兩個屬性僅IE8及以下版本支持,IE9+使用這兩個屬性會報錯。
終于寫完了,這篇寫得時間好長……這樣整理完知識脈絡會清晰一點吧~
本文主要參考《js高級程序設計》事件一章。如有不妥之處,還請指正。謝謝!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/49602.html
摘要:指定事件處理程序指定事件處理程序主要有兩種方式級事件處理程序級事件處理程序。添加事件處理程序注意這里是哦或移除事件處理程序使用移除事件處理程序的條件與方法相同必須提供相同的參數,從而添加的匿名函數也無法被移除。 今天看書又看到事件,遂決定小總結一下~ JavaScript與HTML之間的交互是通過事件實現的。事件,就是文檔或瀏覽器窗口中發生的一些特定的交互瞬間。可以使用監聽器(事件處...
摘要:說明本文主要學習下的模型觀察者,把一點點經驗分享出來希望對別人能有幫助。模型觀察者這個功能能做很多事情,比如模型更新時發個通知。總結本篇文章主要學了下的模型觀察者,發現這個功能也能使代碼結構更清晰,覺得挺好的。 說明:本文主要學習下Laravel的Model Observer模型觀察者,把一點點經驗分享出來希望對別人能有幫助。同時,作者會將開發過程中的一些截圖和代碼黏上去,提高閱讀效率...
摘要:與不同的是,應該以發送的數據作為請求的主體。有了這些不同的事件支持,開發者可以免去檢查之類的工作,更加的方便。其中事件和事件比較重要。而事件則會為在瀏覽器接收數據期間周期性地觸發。 在上篇筆記中,我們主要談了一些概述和跨域的問題,這一次我們聊聊請求和響應的具體內容。 向服務器發起請求 我們在創建了XHR對象后,接著需要用兩個方法來發送請求:open()和send(),這兩個方法有點像賽...
摘要:原文地址一個非常適合入門學習的博客項目前端掘金一個非常適合入門學習的項目,代碼清晰結構合理新聞前端掘金介紹一個由編寫的新聞。深入淺出讀書筆記知乎專欄前端專欄前端掘金去年的一篇老文章,恰好今天專欄開通,遷移過來。 破解前端面試(80% 應聘者不及格系列):從閉包說起 - 掘金修訂說明:發布《80% 應聘者都不及格的 JS 面試題》之后,全網閱讀量超過 6W,在知乎、掘金、cnodejs ...
摘要:原文地址一個非常適合入門學習的博客項目前端掘金一個非常適合入門學習的項目,代碼清晰結構合理新聞前端掘金介紹一個由編寫的新聞。深入淺出讀書筆記知乎專欄前端專欄前端掘金去年的一篇老文章,恰好今天專欄開通,遷移過來。 破解前端面試(80% 應聘者不及格系列):從閉包說起 - 掘金修訂說明:發布《80% 應聘者都不及格的 JS 面試題》之后,全網閱讀量超過 6W,在知乎、掘金、cnodejs ...
閱讀 3093·2021-09-22 15:54
閱讀 3981·2021-09-09 11:34
閱讀 1767·2019-08-30 12:48
閱讀 1161·2019-08-30 11:18
閱讀 3431·2019-08-26 11:48
閱讀 913·2019-08-23 17:50
閱讀 2119·2019-08-23 17:17
閱讀 1240·2019-08-23 17:12