先來說說什麼是「事件」呢?
舉個例子:看到紅燈,就踩剎車!
「看到紅燈」就是事件;「踩剎車」就是事件發生後所採取的行動。而在網頁上所發生的事件,可能是使用者滑鼠點擊、滑鼠移入、滾動瀏覽器卷軸、改變視窗大小…等等。
瀏覽器載入網頁時,會把所有的JavaScript程式碼載入,但是並不是所有程式碼都會馬上執行,有些必須等到「事件發生」,才會執行相對應的程式碼,例如,「按下按鈕」,跳出「對話框」。「按下按鈕」是事件(Event),「跳出對話框」就是執行相對應的程式碼(Event Handler)。
當然你必須要把監聽的事件(Event)跟你要執行的程式碼(Event Handler)綁定在一起,事件發生時兩者才會連動。
目前綁定的方法有:
在HTML元素上透過「on + 事件名稱」來綁定事件,只要事件被觸發,就會執行JavaScript。
<button id="btn" onclick="alert('降龍十八掌之亢龍有悔')">點擊出招</button>
在早期都是透過這種方式綁定事件,但隨著觀念的進化,這種「侵入式的寫法」容易造成資安漏洞,也不符合「關注點分離」,由HTML負責架構與內容,JavaScript負責互動的觀念。現在比較少用這種綁定事件的方式了。
也可以在JavaScript中藉由document.getElementById()或document.querySelector()選取HTML元素當節點,然後將on-event綁定在選取的節點上。
<button id="btn">點擊出招</button>
//選取節點
let btn = document.getElementById('btn');
//將on-event綁定在事件上
btn.onclick = function(){
alert('降龍十八掌之見龍在田');
};
如果希望HTML一載入瀏覽器,JavaScript就自動執行,可以這樣寫:
window.onload = function(){
alert('飛雪連天射白鹿,笑書神俠倚碧鴛');
}
為了要偵測使用者對網頁所做的行為,如果可以在網頁中埋伏一個間諜,監看使用者是否有對指定的元素做出設定好的動作,如果有的話,就給予相對的回應,這樣就會方便得多。
那該如何來做事件監聽呢?基本上「事件監聽」長成這個樣子:
HTML元素節點.addEventListener('事件名稱',事件處理器,boolean值)
「事件名稱」指的是使用者對綁定的HTML元素節點所做的事情,例如點擊(click)、滑鼠移入(mouseenter)…等事件。
「事件處理器」(Event Handler)指的是事件發生時,要叫用的function()。
布林值(boolean),false代表事件冒泡(Event Bubbling),而true代表事件捕捉(Event Capturing)。這是甚麼意思呢?
事件冒泡(Event Bubbling):由啟動事件的元素節點開始,向外層傳遞。
事件捕捉(Event Capturing):由最外層開始,一層一層找到啟動事件的元素節點。
<!DOCTYPE html>
<html>
<head>
<title>標題</title>
</head>
<body>
<div>點我--隔山打牛--點我</div>
</body>
事件觸發的傳遞順序會是:
<div>
點我--隔山打牛--點我</div>
<body>
<html>
因為<div>
點我--隔山打牛--點我</div>
也是在<body>
的範圍中,所以點擊它的同時也會傳遞到<body>
,跟著也會傳到<html>
與document。這種click事件一層一層往上依序被觸發,就是「事件冒泡」機制。
而「事件捕獲」傳遞的順序則相反,同樣是點擊<div>
點我--隔山打牛--點我</div>
,但是傳遞順序卻如下:
<html>
<body>
<div>
點我--隔山打牛--點我</div>
講解完事件綁定,來看一下事件綁定的簡單例子:
<button id="btn">用滑鼠點穴</button>
let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
alert('腳麻袂凍行');
},false)
而且同元素的同一事件可以重複指定addEventListener():
let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
alert('腳麻袂凍行');
},false)
btn.addEventListener('click',function(){
alert('快吃循力寧');
},false)
如果是on-event的方法如果重複綁定的話,則只會出現最後一個綁定的事件。
<input type="button" onclick = "alert('見龍在田')" value="行內綁定">
<!-- 使用on-event綁定 -->
<input type="button" class="btnOn" value="on-event點擊">
<!-- 使用addEventListener綁定 -->
<input type="button" class="btnAdd" value="addEvent點擊">
var elOn = document.querySelector('.btnOn');
elOn.onclick = function(){
alert('on-1');
}
//雖然同一物件綁訂了兩個on事件處理器,但是只會出現最後一個on-2
elOn.onclick = function(){
alert('on-2');
}
var elAdd = document.querySelector('.btnAdd');
elAdd.addEventListener('click',function(){
alert('add點擊1');
},false)
//同一物件綁訂了兩個addEventListener,兩個綁定的事件處理器都會執行
elAdd.addEventListener('click',function(){
alert('add點擊2');
},false)
那如果要解除addEventListener()綁定的事件,可以使用removeEventListener()。
HTML元素節點.addEventListener('事件名稱',事件處理器,boolean值)
but,要注意的是「事件處理器」必須要指向同一個「實體」,在下面範例中指的是相同名稱的function。
let btn = document.getElementById('btn');
btn.addEventListener('click',function(){
alert('腳麻袂凍行');
},false)
//愛到不能動,還有甚麼值得我心痛,沒辦法移除事件,因為指向不同實體
btn.removeEventListener('click',function(){
alert('腳麻袂凍行');
},false)
要這麼做才行:
let btn = document.getElementById('btn');
let canNotMove = function() {
alert('腳麻袂凍行');
}
btn.addEventListener('click', canNotMove, false);
btn.removeEventListener('click', canNotMove, false);