原本中午就要開工,但是到自己的主頁時,默默的就把個人背景打完,然後找了張還能看(?的照片放上去,不然都只有熊熊的圖案。
看能不能多幾個訂閱或追蹤
昨日講完了 JS 對於 DOM 常見的操作方法,那接下來就剩最後一個部分(遞mic~
好吧,台下沒有觀眾,只好我們自問自答 Yo
在 Day14 有提到,基本上在前端 JS 用於與使用者互動,像是使用者點了這個按鈕,接著 JS 進行後續動作。
也就是總共分為三個部分
那 1
、3
我們前兩天講完了,也就是能夠選取要操作的元素(那個按鈕)、以及對於該元素常用的操作方法(後續動作)。
剩下的就是今天要講的事件 Event
(點選),有了按鈕還有準備要進行的動作,就只差了需要知道使用者何時點選的這個方法了。
此種方法不推薦,雖然方便,但是程式碼一多時就會很髒,而且也難維護。
<h1 onclick="alert('clicked')">inline</h1>
當事件觸發時,會自動把事件的詳細資訊傳入 callback function 中的第一個參數,通常會命名為 e
或 event
。
但是要非常注意,這種寫法同一個元素的同一個事件只能綁定一次。
也就是下方範例中,點選 body 時,照理要依序跳出 Hi1 => Hi2,但是實際只會跳出 Hi2!
var myBody = document.body;
myBody.onclick = function(e){
alert('Hi1');
};
myBody.onclick = function(e){
alert('Hi2');
};
// Hi2
也可以將 callback function 設為具名函數
document.body.onclick = sayHi;
function sayHi(e){
alert('Hi');
};
myBody.onclick = null;
addEventListener
不會有前一個綁定方法遇到的問題,也就是 body 綁定兩個 click 事件,也會依序跳出兩個 Hi。
var myBody = document.body;
myBody.addEventListener('click', function(e){
alert('clicked');
}, false);
addEventListener
的第三個參數決定事件處理是 Event Bubbling(事件氣泡)
還是 Event Capturing(事件捕捉)
。
false
: 預設(可不寫),由內找到外。true
: 由外找到內。這邊舉一個例子會比較清楚:
點 click me 時,預設(false)情況下,console 會先印出 li
,再印出 ul
。
但是改成 true
時,則會先印出 ul
,再印出 li
。
<ul id="ul">
<li id="li">click me</li>
</ul>
var ul = document.querySelector("#ul");
var li = document.querySelector("#li");
ul.addEventListener('click', function(e){
console.log('ul clicked');
}, false);
li.addEventListener('click', function(e){
console.log('li clecked');
}, false);
同樣也可以將 callback function 設為具名函數
document.body.addEventListener('click', sayHi);
function sayHi(e){
alert('Hi');
};
document.body.removeEventListener('click', sayHi);
上面介紹了 3 種綁定方法,當事件發生時,會有一個參數自動帶入 callback function,也就是我們常命名的 e
、event
。
讓我們接著看看這個事件詳細資訊有什麼用法吧。
上一個例子,點 click me 時,會先顯示 li
,再往外顯示 ul
。
很多情況會遇到這種元素重疊的問題,當我們只想顯示點擊的 li
時,可以把冒泡中止,不讓它再往外找。
ul.addEventListener('click', function(e){
console.log('ul clicked');
}, false);
li.addEventListener('click', function(e){
e.stopPropagation(); // 此處終止了冒泡事件
console.log('li clecked');
}, false);
有些元素會有默認行為,像是 a 連結
點它會自動跳轉、submit
點擊會自動把表單內容送出。
當我們不想讓它的預設動作執行時,可以取消它,像是前端想先檢查表單內容是否正確再傳到後端,所以要阻止 submit
點擊後就把內容送出。
<a href="http://www.google.com" id="link">myLink</a>
var link = document.querySelector("#link");
link.addEventListener('click', function(e){
e.preventDefault(); // 此處阻止跳轉到 google.com
console.log('link no jump');
}, false);
當然 e
裡面也可以取得觸發該事件的元素資訊。
EX:
我們將 click
事件綁定在最外面的 div,接著點選 div 中的元素,範例中點選 li 的連結,
可以看到 callback function 中分別印出該元素的結構、元素名、ID...。
<div class="header">
<ul style="border: 1px solid black; padding: 10px">
<li><a href="#" id="link">123</a></li>
</ul>
</div>
var header = document.querySelector(".header");
header.addEventListener('click', function(e){
// console.log(e.target);
// EX: LI
console.log(e.target.nodeName);
// EX: link
console.log(e.target.id);
});
<div class="header">
<ul style="border: 1px solid black; padding: 10px; list-style: none">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
Q: 請問若是想顯示點擊的
li
內容該怎麼做?
A: 綁定每個li
再顯示。
var li = document.querySelectorAll('.header ul li');
for(var i = 0; i < li.length; i++){
li[i].addEventListener('click', showText);
}
function showText(e){
console.log(e.target.textContent);
}
但是這樣需要個別綁定,效率較低,而且動態新增的元素不會被綁定。
較好的做法是綁定 li
的父元素來監聽,也就是結合上方提到的 e.target
。
var header = document.querySelector(".header");
header.addEventListener('click', function(e){
if(e.target.nodeName == "LI"){
console.log(e.target.textContent);
}
});
screen
計算滑鼠在整個螢幕之位置(算入解析度)page
計算在瀏覽器中的網頁頁面之位置client
計算在瀏覽器中的位置知道滑鼠座標也可以把滑鼠圖示改變(覆蓋)成自訂圖案XD
<body style="min-height: 100vh; cursor: none">
<div>
<p>
screenX: <span class="screenX"></span>
screenY: <span class="screenY"></span>
</p>
<p>
pageX: <span class="pageX"></span>
pageY: <span class="pageY"></span>
</p>
<p>
clientX: <span class="clientX"></span>
clientY: <span class="clientY"></span>
</p>
</div>
<div class="mouseImg" style="position: absolute">
<img src="https://upload.wikimedia.org/wikipedia/commons/1/1b/Creative-Tail-Animal-dog.svg" width="50px">
</div>
</body>
var screenX = document.querySelector('.screenX');
var screenY = document.querySelector('.screenY');
var pageX = document.querySelector('.pageX');
var pageY = document.querySelector('.pageY');
var clientX = document.querySelector('.clientX');
var clientY = document.querySelector('.clientY');
var mouseImg = document.querySelector('.mouseImg');
var body = document.body;
body.addEventListener('mousemove', getPosition, false);
function getPosition(e){
screenX.textContent = e.screenX;
screenY.textContent = e.screenY;
pageX.textContent = e.pageX;
pageY.textContent = e.pageY;
clientX.textContent = e.clientX;
clientY.textContent = e.clientY;
mouseImg.style.left = e.clientX + 'px';
mouseImg.style.top = e.clientY + 'px';
}
原本想要一次打完,但發現篇幅有點多,決定把常用的事件放到明天來介紹。
今日的分享就到這,我們明天見