addEventListener 監聽、Event Bubbling 事件冒泡、Event Capturing 事件捕捉、stopPropagation 終止冒泡事件、preventDefault 取消預設、e.target 搭配 nodeName 與 keyCode 、表單中 blur, focus, click 事件、keydown 事件、mousemove, mouseleave 事件、網頁座標 ( screen、page、client )。
<input type="button" onclick="alert('Hello')" value="點擊" class='btn'>
在 HTML 中執行 JS ( 以 onclick
為例 ),不推薦的原因 :
綁定
執行 onclick
,不像 HTML 中 onclick
會一直執行。onclick
中被插入惡意程式碼。btn.addEventListener('click' , function(){ },false)
addEventListener( '參數1' ,參數2 ,參數3 );
參數1
: 選擇事件,例如 "click"
亦可換為其他事件。滑鼠的各種事件可參閱 w3school - HTML DOM Events 。參數2
: function(e){}
,函式內可加入 e
,會回傳 event
事件。參數3
: false
。
true
: 從外層往內層找指定元素。false
( 預設 ) : 指定元素往外層找,預設為 false
,所以如果沒寫就會是預設狀態。出處 : JavaScript 工程師養成直播班 - 2021 春季班影音
為什麼 let count = 0;
不能放在 function(e){}
內 ?
函式內的大括號 {}
執行完會釋放記憶體,如果不希望值因函式運算完而消失,就需要放在外層,函式內運算完就會往外送依序做加總。
出處 : JavaScript 工程師養成直播班 - 2021 春季班影音
DOM events 事件,例如滑鼠的各種事件可參閱 w3school - HTML DOM Events ,但現在不推薦在 HTML 使用 JS,因爲較老式用法有許多缺點下方會說到。
clientX
,可從函式參數 e
去讀取裡面的屬性 clientX
。e
( 參數名可自訂 ),所以點擊按鈕後會把所有物件 ( MouseEvent 為物件 object ) 資訊紀錄到這個參數內。
onclick
與 addEventListener( "click" , function(e){},false)
差異 ?onclick
不能同時綁定兩個事件。如果綁定兩個事件以上,只會讀取最後一個。addEventListener( "click", function(e){}, false);
可以同時綁定多個事件。addEventListener ()
中 true
與 false
差異?true
( Event Capturing 事件捕捉 )
false
( Event Bubbling 事件汽泡 )
false
,所以如果沒寫就會是預設狀態。false
,點擊最近的東西來去觸發事件。.body
與 .box
為 false,點選 box 區域時會先執行哪個呢 ?false
( Event Bubbling 事件汽泡 ) : 指定元素往外找 。以範例來說,當下點的指定元素 .box
往外層找 .body
→ 先跳出 box 彈跳視窗再出現 body 彈跳視窗true
( Event Capturing 事件捕捉 ) : 從最外層往內找到指定元素。以範例來說,外層 .body
往內找到指定元素 .box
→ 先跳出 body 彈跳視窗再出現 box 彈跳視窗false
,點擊最近的東西來去觸發事件。body
為 true , .box
為 false,點選 box 區域時會先執行哪個呢 ?.box
區域於 body
範圍內,而 body
的 addEventListener
是設定 true
( 從外層找到指定元素 ),所以會先跳 body
再跳 .box
。防止監聽的元素互相衝突
當點選到重疊的元素時,只希望執行一個元素。可使用 stopPropagation
當指定元素和上層元素有重疊時,會阻止指定元素往外層找。
stopPropagation
,點擊 .box
會彈出 box
與 body
視窗 ( 事件冒泡由指定元素往外執行 )。.box
加上 stopPropagation
後終止冒泡事件,點擊 .box
後就只會彈出 box
的 alert 視窗。stopPropagation
囉!常使用的情境:
preventDefault
取消預設觸發行為後,點擊 a 連結就不會轉跳到 google 頁面。e.target
可知道目前點擊的 DOM 範圍。
li
與 a 標籤,可於開發者工具看見這兩個 DOM 的範圍。console.log (e);
部分,開啟開發者工具也可以看到點擊元素的目前所在位置 target : li
。nodeName
為 DOM 元素的節點,可搭配 e.target
使用。
出處 : JavaScript 工程師養成直播班 - 2021 春季班影音
<input type="button" value="點擊" class='btn'>
<ul class="list">
<li>標題 1</li>
<li>標題 2
<input type="button" class="btn" value="按鈕">
</li>
</ul>
const btn = document.querySelector('.btn');
const list = document.querySelector('.list');
btn.addEventListener('click', function (e) {
console.log(e.target.innerHTML); //點擊 input 因為裡面沒有 HTML 結構,所以會顯示空值。
console.log(e.target.nodeName); //INPUT
})
// 下方為點擊 li 標題2 的按鈕(下圖一)
list.addEventListener('click', function (e) {
console.log(e.target.innerHTML); //點擊 input 因為裡面沒有 HTML 結構,所以會顯示空值。
console.log(e.target.nodeName); //INPUT
})
//點擊第二個 li 的標題2文字 (下圖二)
list.addEventListener('click', function (e) {
console.log(e.target.innerHTML); //顯示 → 標題 與 input 結構
console.log(e.target.nodeName); //LI
})
// 點擊第二個 li 標題內的按鈕 button ▲ ( 圖一 )
// 點擊第二個 li 的標題文字 ▲ ( 圖二 )
<ul class="list">
<li>標題</li>
<li>標題
<input type="button" class="btn" value="按鈕">
</li>
</ul>
.list
這個 DOM。所以 ul.list > li *2
以內的範圍都會被綁定。ul.list > li *2
範圍內觸發 click,就會觸發函式。e.target.nodeName
會顯示 DOM 元素點擊到的節點為 INPUT
標籤。e.target.nodeName
與點擊到的DOM 節點是否相同,是的話就觸發大括號 {}
內的程式碼。<select id="areaId">
<option selected disabled>請選取區域</option>
<option value="苓雅區">苓雅區</option>
<option value="前鎮區">前鎮區</option>
</select>
<ul class="list"></ul>
const country = [
{
farmer: '查理',
place: '苓雅區'
},
{
farmer: '布朗',
place: '前鎮區'
},
{
farmer: '派翠克',
place: '苓雅區'
},
]
change
時會觸發後方函式。forEach
撈出變數 country
內的陣列資料,並使用判斷式篩選,讓選單的值與 forEach
撈出的 place
相同時,列出農夫名字。
e.target.value
可撈出選單中文字欄位內的值。let str = '';
,等跑完 forEach
再帶到 li 內 。
let str = '';
,來做累加字串。list.innerHTML
。備註
list.innerHTML = str;
寫在 forEach
內與外雖然網頁皆顯示無誤,但對運行程式碼的效能考量不理想。
forEach
內運行的次數會和陣列長度一樣。forEach
外只會運行一次。focus
所在焦點blur
離開焦點focus
事件,當元素失去焦點時,會觸發 blur
事件。以表單為例,滑鼠點擊表單要輸入數字 ( 點擊了表單即觸發 focus
事件 ),但沒輸入就離開 ( 再點擊表單外的區域 ),就會觸發 blur
事件。
// 未填寫表格就點選計算中按鈕,會出現 NaN ▲
<h2>六角西餐廳 - 顧客點餐系統</h2>
<ul>
<li>
服務生 : Hello,請問你想要點甚麼 ?
</li>
<li>
顧客 : 給我
<input type="text" class="hamburgerId">
個漢堡,再
<input type="text" class="cokeId">
杯可樂。
</li>
<li>
服務生:
<button class="startCountId">計算</button>
,好的,總計是
<em class="totalId"></em>
元
</li>
</ul>
//歸戶
const hamNum = document.querySelector('.hamburgerId');
const cokeNum = document.querySelector('.cokeId');
const startCount = document.querySelector('.startCountId');
const total = document.querySelector('.totalId');
// 漢堡與可樂價錢
const hamPrice = 70;
const cokePrice = 50;
isNaN
判斷是否為數字
isNaN
函數用來判斷參數是否為特殊的非數字值 NaN
,如果是就回傳 true
,不是則回傳 false
,要注意的是 isNaN
函數會將參數轉換成數字 ( number ),如果轉換成功就會回傳 true
,失敗則回傳 false
。return
和 return false
的差異為何呢 ? ( 助教回覆 )Ans :return
在函式內使用,會回傳一個值,並終止函式往下執行。return false
通常用來阻止提交表單或是繼續執行下面的程式碼。簡單來說就是阻止執行預設的行為。
.
return false;
return false;
下方 1 與 2 的事情它都會做:
event.preventDefault();
。event.stopPropagation();
。return
回來。出處 : event.preventDefault()跟return false的差別是?
鍵盤式移動的遊戲,或互動式網站可使 keyCode
const body = document.body;
body.addEventListener('keydown', (e) => {
console.log(e.keyCode);
})
keydown
指按下鍵盤的那個剎那,任何的鍵盤按鍵按下都可以取得對應的鍵盤代碼,也就是所謂的 keyCode
。keyCode
。renderCode()
把 keyCode
渲染在畫面上。keydown
查出按鍵 1、2、3 的 keyCode
。switch
做控制判斷。Document.body
<body>
、<table>
與其它的元素 )的進入點。Document.body
主要是「 回傳目前文件的 <body>
節點,如元素不存在則回傳 null
」,因此只有 body
能使用。mousemove
滑鼠移動到指定元素後觸發。
mouseleave
滑鼠離開指定元素後觸發。
mousemove
搭配 setAttribute
讓滑鼠進入 box 區域後,讓 box 由方形變圓形。mousemove
搭配 setAttribute
讓滑鼠進入 box 區域後,讓 box 由方形變圓形。mouseleave
讓滑鼠離開 box 區域後再變回方形。
classList.remove
刪除圓形 boxRadius
,再使用 classList.add
新增回原本方形 box
// 刪除單個
document.getElementById("myDIV").classList.remove("mystyle");
// 刪除多個
document.getElementById("myDIV").classList.remove("mystyle", "anotherClass", "thirdClass");
animation
與 JS 的 mousemove
做小遊戲animation
屬性的應用可參閱 「 Day8 | Animation、Transition、Transform 動畫效果 」classList
DOM 裡每個節點都有一個 classList
物件,可以使用來新增、刪除、修改節點上的 CSS 。
remove
add
toggle
可先開啟 CodePen 範例 搭配下方解說
螢幕 ( 手機、平板 、電腦等裝置 ) 解析度的座標點
pageY
座標點數字會持續增加,而 clientY
只會顯是當下瀏覽器高度的座標點。pageY
座標點數字會持續增加,而 clientY
只會顯是當下瀏覽器高度的座標點。function showPosition(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;
}
解說
e
為 showPosition
函式中的參數,可顯示出 showPosition
函式的所有資訊。console.log(e)
可顯示函示的所有資訊 ▲console.log(e)
顯示的函式資訊。
screenX
為例 → e.screenX
( 亦可換 screenX
、screenY
、target
.. 等 ) 搭配 textContent
,可把 screen X
座標資訊顯示在網頁上。CSS
cursor:none;
.mouseImg
使用 fixed 可以不會因為旁邊的捲軸滾動而影響到位置 → 如圖 ,但使用 absolute
就會因為卷軸滾動而讓 icon 移動到上方 如圖 。JS
如何讓圖案取代的鼠標 & 原來的鼠標同步 ?
querySelector()
只會讓第一個子元素會獲得監聽querySelector()
的特性只會抓第一筆資料做更新。
// 點選湯姆區域,Console 顯示節點為 LI ▲
e.target.nodeName
點擊區域內項目可確定是否有點擊到需要的節點。使用情境:
ul>li
為例:
ul
,每個子元素 li
皆可獲得監聽。解析:
nodeName
方式查詢到 li 們的節點為 LI 把它帶入判斷式 if 中 → if( e.target.nodeName !== 'LI' ){return}
點擊到的節點不等於 li 回傳 return
console.log()
就不執行 ) 。console.log(e.target.nodeName);
點選 li 內的湯姆與捷克, Console 出現的節點為 LI 所以判斷式內寫 !== 'LI'
<div class="box">
<ul class="boxList">
<li>01. coco</li>
<li>02. coxima</li>
</ul>
</div>
<div class="box2">
<ul class="box2List"></ul>
</div>
box2Data
,點擊 .boxList>li
的文字可以 push 到空陣列中,再渲染到 .box2List
內。