您好,登錄后才能下訂單哦!
這篇文章主要介紹JavaScript事件是什么意思,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
JavaScript事件是指在文檔或者瀏覽器中發生的一些特定交互瞬間,比如打開某一個網頁,瀏覽器加載完成后會觸發load事件,當鼠標懸浮于某一個元素上時會觸發hover事件,當鼠標點擊某一個元素時會觸發click事件等等。
本文操作環境:Windows7系統、javascript1.8.5版、DELL G3電腦
JavaScript事件是指什么?
JavaScript 事件詳解
事件是指在文檔或者瀏覽器中發生的一些特定交互瞬間,比如打開某一個網頁,瀏覽器加載完成后會觸發 load
事件,當鼠標懸浮于某一個元素上時會觸發 hover
事件,當鼠標點擊某一個元素時會觸發 click
事件等等。
事件處理就是當事件被觸發后,瀏覽器響應這個事件的行為,而這個行為所對應的代碼即為事件處理程序。
瀏覽器會根據一些事件作出相對應的事件處理,事件處理的前提是需要監聽事件,監聽事件的方法主要有以下三種:
即在 HTML 元素里直接填寫與事件相關的屬性,屬性值為事件處理程序。示例如下:
<button onclick="console.log('You clicked me!');"></button>
onclick
對應著 click
事件,所以當按鈕被點擊后,便會執行事件處理程序,即控制臺輸出 You clicked me!
。
不過我們需要指出的是,這種方式將 HTML 代碼與 JavaScript 代碼耦合在一起,不利于代碼的維護,所以應該盡量避免使用這樣的方式。
通過直接設置某個 DOM 節點的屬性來指定事件和事件處理程序,上代碼:
const btn = document.getElementById("btn"); btn.onclick = function(e) { console.log("You clicked me!"); };
上面示例中,首先獲得 btn 這個對象,通過給這個對象添加 onclick
屬性的方式來監聽 click
事件,這個屬性值對應的就是事件處理程序。這段程序也被稱作 DOM 0 級事件處理程序。
標準的事件監聽函數如下:
const btn = document.getElementById("btn"); btn.addEventListener("click", () => { console.log("You clicked me!"); }, false);
上面的示例表示先獲得表示節點的 btn 對象,然后在這個對象上面添加了一個事件監聽器,當監聽到 click
事件發生時,則調用回調函數,即在控制臺輸出 You clicked me!
。addEventListener
函數包含了三個參數 false,第三個參數的含義在后面的事件觸發三個階段之后再講解。這段程序也被稱作 DOM 2 級事件處理程序。IE9+、FireFox、Safari、Chrome 和 Opera 都是支持 DOM 2 級事件處理程序的,對于 IE8 及以下版本,則用 attacEvent()
函數綁定事件。
所以我們可以寫一段具有兼容性的代碼:
function addEventHandler(obj, eventName, handler) { if (document.addEventListener) { obj.addEventListener(eventName, handler, false); } else if (document.attachEvent) { obj.attachEvent("on" + eventName, handler); } else { obj["on" + eventName] = handler; } }
在為某個元素綁定了一個事件后,如果想接觸綁定,則需要用到 removeEventListener
方法。看如下例子:
const handler = function() { // handler logic } const btn = document.getElementById("btn"); btn.addEventListener("click", handler); btn.removeEventListener("click", handler);
需要注意的是,綁定事件的回調函數不能是匿名函數,必須是一個已經被聲明的函數,因為解除事件綁定時需要傳遞這個回調函數的引用。
同樣,IE8 及以下版本也不支持上面的方法,而是用 detachEvent
代替。
const handler = function() { // handler logic } const btn = document.getElementById("btn"); btn.attachEvent("onclick", handler); btn.detachEvent("onclick", handler);
同樣,可以寫一段具有兼容性的刪除事件函數:
function removeEventHandler(obj, eventName, handler) { if (document.removeEventListener) { obj.removeEventListener(eventName, handler, false); } else if (document.detachEvent) { obj,detachEvent("on" + eventName, handler); } else { obj["on" + eventName] = null; } }
事件流描述了頁面接收事件的順序。現代瀏覽器(指 IE6-IE8 除外的瀏覽器,包括 IE9+、FireFox、Safari、Chrome 和 Opera 等)事件流包含三個過程,分別是捕獲階段、目標階段和冒泡階段,下圖形象地說明這個過程:
下面就詳細地講解這三個過程。
當我們對 DOM 元素進行操作時,比如鼠標點擊、懸浮等,就會有一個事件傳輸到這個 DOM 元素,這個事件從 Window 開始,依次經過 docuemnt、html、body,再不斷經過子節點直到到達目標元素,從 Window 到達目標元素父節點的過程稱為捕獲階段,注意此時還未到達目標節點。
捕獲階段結束時,事件到達了目標節點的父節點,最終到達目標節點,并在目標節點上觸發了這個事件,這就是目標階段。
需要注意的是,事件觸發的目標節點為最底層的節點。比如下面的例子:
<div> <p>你猜,目標在這里還是<span>那里</span>。</p> </div>
當我們點擊“那里”的時候,目標節點是<span></span>
,點擊“這里”的時候,目標節點是<p></p>
,而當我們點擊<p></p>
區域之外,<p></p>
區域之內時,目標節點就是<p></p>
。
當事件到達目標節點之后,就會沿著原路返回,這個過程有點類似水泡從水底浮出水面的過程,所以稱這個過程為冒泡階段。
針對這個過程,wilsonpage 做了一個 DEMO,可以非常直觀地查看這個過程。
現在再看 addEventListener(eventName, handler, useCapture)
函數。第三個參數是 useCapture,代表是否在捕獲階段進行事件處理, 如果是 false, 則在冒泡階段進行事件處理,如果是 true,在捕獲階段進行事件處理,默認是 false。這么設計的主要原因是當年微軟和 netscape 之間的瀏覽器戰爭打得火熱,netscape 主張捕獲方式,微軟主張冒泡方式,W3C 采用了折中的方式,即先捕獲再冒泡。
上面我們講了事件的冒泡機制,我們可以利用這一特性來提高頁面性能,事件委托便事件冒泡是最典型的應用之一。
何謂“委托”?在現實中,當我們不想做某件事時,便“委托”給他人,讓他人代為完成。JavaScript 中,事件的委托表示給元素的父級或者祖級,甚至頁面,由他們來綁定事件,然后利用事件冒泡的基本原理,通過事件目標對象進行檢測,然后執行相關操作。看下面例子:
// HTML <ul id="list"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> <li>Item 5</li> </ul> // JavaScript var list = document.getElementById("list"); list.addEventListener("click", function(e) { console.log(e.target); });
上面的例子中,5 個列表項的點擊事件均委托給了父元素 <ul id="list"></ul>
。
先看看事件委托的可行性。有人會問,當事件不是加在某個元素上的,如何在這個元素上觸發事件呢?我們就是利用事件冒泡的機制,事件流到達目標元素后會向上冒泡,此時父元素接收到事件流便會執行事件執行程序。有人又會問,被委托的父元素下面如果有很多子元素,怎么知道事件流來自于哪個子元素呢?這個我們可以從事件對象中的 target
屬性獲得。事件對象下面會詳細講解。
我們再來看看為什么需要事件委托。
減少事件綁定。上面的例子中,也可以分別給每個列表項綁定事件,但利用事件委托的方式不僅省去了一一綁定的麻煩,也提升了網頁的性能,因為每綁定一個事件便會增加內存使用。
可以動態監聽綁定。上面的例子中,我們對 5 個列表項進行了事件監聽,當刪除一個列表項時不需要單獨刪除這個列表項所綁定的事件,而增加一個列表項時也不需要單獨為新增項綁定事件。
看了上面的例子和解釋,我們可以看出事件委托的核心就是監聽一個 DOM 中更高層、更不具體的元素,等到事件冒泡到這個不具體元素時,通過 event 對象的 target 屬性來獲取觸發事件的具體元素。
事件委托是事件冒泡的一個應用,但有時候我們并不希望事件冒泡。比如下面的例子:
const ele = document.getElementById("ele"); ele.addEventListener("click", function() { console.log("ele-click"); }, false); document.addEventListener("click", function() { console.log("document-click"); }, false);
我們本意是當點擊 ele 元素區域時顯示 "ele-click",點擊其他區域時顯示 "document-click"。但是我們發現點擊 ele 元素區域時會依次顯示 "ele-click" "document-click"。那是因為綁定在 ele 上的事件冒泡到了 document 上。想要解決這個問題,只需要加一行代碼:
const ele = document.getElementById("ele"); ele.addEventListener("click", function(e) { console.log("ele-click"); e.stopPropagation(); // 阻止事件冒泡 }, false); document.addEventListener("click", function(e) { console.log("document-click"); }, false);
我們還能用 e.cancelBubble = true
來替代 e.stopPropagation()
。網上的說法是 cancelBubble
僅僅適用于 IE,而 stopPropagation
適用于其他瀏覽器。但根據我實驗的結果,現代瀏覽器(IE9 及 以上、Chrome、FF 等)均同時支持這兩種寫法。為了保險起見,我們可以采用以下代碼:
function preventBubble(e) { if (!e) { const e = window.event; } e.cancelBubble = true; if (e.stopPropagation) { e.stopPropagation(); } }
Event 對象代表事件的狀態,比如事件在其中發生的元素、鍵盤按鍵的狀態、鼠標的位置、鼠標按鈕的狀態。當一個事件被觸發的時候,就會創建一個事件對象。
我們用下面的代碼打印出事件對象:
<div id="list"> <li>Item 1</li> <li>Item 2</li> </div> <script> var list = document.getElementById("list"); list.addEventListener("click", function(e) { console.log(e); }); </script>
chrome 49 的運行結果如下:
下面介紹一些比較常用的屬性和方法。
target 與 srcElement 完全相同;
target 指觸發事件的元素, currentTarget 指事件所綁定的元素;
relatedTarget: 與事件的目標節點相關的節點。對于 mouseover 事件來說,該屬性是鼠標指針移到目標節點上時所離開的那個節點。對于 mouseout 事件來說,該屬性是離開目標時,鼠標指針進入的節點。
對于其他類型的事件來說,這個屬性沒有用;
fromElement 和 toElement 僅僅對于 mouseover 和 mouseout 事件有效。
以上面的例子說明,當點擊 <li>Item 1</li>
時,target 就是 <li>Item 1</li>
元素,而 currentTarget 是 <p id="list"></p>
。
上圖:
offsetX/Y: 點擊位置相對于所處元素左上角的位置;
clientX/Y: 點擊位置相對于瀏覽器內容區域左上角的位置;
screenX/Y: 點擊位置相對于屏幕左上角的位置;
pageX/Y: 點擊位置相對整張頁面左上角的位置;
pageX/Y 與 clientX/Y 一般情況下會相同,只有出現滾動條時才不一樣。
altKey: 返回當事件被觸發時,"ALT" 是否被按下;
ctrlKey: 返回當事件被觸發時,"CTRL" 鍵是否被按下;
shiftKey: 返回當事件被觸發時,"SHIFT" 鍵是否被按下;
type: 返回當前 Event 對象表示的事件的名稱
bubbles: 返回布爾值,指示事件是否是起泡事件類型;
cancelable: 返回布爾值,指示事件是否可擁可取消的默認動作;
eventPhase: 返回事件傳播的當前階段,有三個值: Event.CAPTURING_PHASE、 Event.AT_TARGET、 Event.BUBBLING_PHASE,對應的值為 1、2、3,分別表示捕獲階段、正常事件派發和起泡階段;
path: 冒泡階段經過的節點;
preventDefault(): 通知瀏覽器不要執行與事件關聯的默認動作;
stopPropagation(): 阻止冒泡;
以上是“JavaScript事件是什么意思”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。