iT邦幫忙

2021 iThome 鐵人賽

DAY 24
0
自我挑戰組

JavaScript老學徒筆記—馬步篇系列 第 25

【Day24】派一個Spy到網頁中竊聽—事件監聽

先來說說什麼是「事件」呢?

舉個例子:看到紅燈,就踩剎車!

「看到紅燈」就是事件;「踩剎車」就是事件發生後所採取的行動。而在網頁上所發生的事件,可能是使用者滑鼠點擊、滑鼠移入、滾動瀏覽器卷軸、改變視窗大小…等等。

瀏覽器載入網頁時,會把所有的JavaScript程式碼載入,但是並不是所有程式碼都會馬上執行,有些必須等到「事件發生」,才會執行相對應的程式碼,例如,「按下按鈕」,跳出「對話框」。「按下按鈕」是事件(Event),「跳出對話框」就是執行相對應的程式碼(Event Handler)。

當然你必須要把監聽的事件(Event)跟你要執行的程式碼(Event Handler)綁定在一起,事件發生時兩者才會連動。

目前綁定的方法有:

  • 由網頁上HTML元素上綁定on-event處理器
  • 利用DOM API所提供的on-event處理器來綁定

在網頁上HTML元素上綁定on-event處理器

在HTML元素上透過「on + 事件名稱」來綁定事件,只要事件被觸發,就會執行JavaScript。

<button id="btn" onclick="alert('降龍十八掌之亢龍有悔')">點擊出招</button>

在早期都是透過這種方式綁定事件,但隨著觀念的進化,這種「侵入式的寫法」容易造成資安漏洞,也不符合「關注點分離」,由HTML負責架構與內容,JavaScript負責互動的觀念。現在比較少用這種綁定事件的方式了。

利用DOM API所提供的on-event處理器來綁定

也可以在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>

事件觸發的傳遞順序會是:

  1. <div>點我--隔山打牛--點我</div>
  2. <body>
  3. <html>
  4. document

因為<div>點我--隔山打牛--點我</div>也是在<body>的範圍中,所以點擊它的同時也會傳遞到<body>,跟著也會傳到<html>與document。這種click事件一層一層往上依序被觸發,就是「事件冒泡」機制。

而「事件捕獲」傳遞的順序則相反,同樣是點擊<div>點我--隔山打牛--點我</div>,但是傳遞順序卻如下:

  1. document
  2. <html>
  3. <body>
  4. <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);

上一篇
【Day23】我變我變我變變變:如何改變HTML元素的樣式
下一篇
事件—天外飛來一個e
系列文
JavaScript老學徒筆記—馬步篇35

尚未有邦友留言

立即登入留言