事件使用

監聽

dom.addEventListener(event, function)

event 事件類型

function 執行函數

let dom = document.querySelector('#dom');

dom.addEventListener('click', function(e) {
    console.log(e);
});

e 事件氣泡,事件觸發時,系統自動傳遞

事件類型

click

點擊觸發

let btn = document.querySelector('#btn');

btn.addEventListener('click', function(e) {
    console.log(e);
});

change

焦點移出時且數值變化時觸發,用於輸入類型元素(有 value 屬性)

let name = document.querySelector('#name');

name.addEventListener('change', function(e) {
    console.log(name.value);
});

blur

焦點移出時觸發(focus -> unfocus)

let name = document.querySelector('#name');

name.addEventListener('blur', function(e) {
    console.log(name.value);
});

chagne 類似,差別在於無論數值有沒有變化都會觸發

keypress

鍵盤按下時觸發

let name = document.querySelector('#name');

name.addEventListener('keypress', function(e) {
    console.log(name.value);
});

keyup

鍵盤放開時觸發

let name = document.querySelector('#name');

name.addEventListener('keyup', function(e) {
    console.log(name.value);
});

補充

keypresskeyup 產生的 e 事件物件會附帶觸發的按鍵

使用 e.key 可以取得觸發的按鍵

let name = document.querySelector('#name');

name.addEventListener('keyup', function(e) {
    console.log(e.key);
});

練習

分數等級轉換

  1. 建立一個數字輸入匡
  2. 建立一個計算按鈕
  3. 當按下計算按鈕時,抓取數字輸入匡進行判斷
  4. 分數等級如下
    1. >= 90 甲
    2. >= 80 乙
    3. >= 70 丙
    4. >= 60 丁
    5. < 60 不及格
  5. 數字輸入匡按下 enter 時,也可以進行計算

demo

事件氣泡

事件監聽很好用,綁定都是針對單一元素處理,如果需要大量綁定,該如何處理?

html

<ul id="menu">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>

點擊每一個 li 都印出當下 li 內容

js

let lis = document.querySelectorAll('#menu li')

lis.forEach(function (li) {
    li.addEventListener('click', function (e) {
        console.log(li.innerHTML)
    })
})

問題

  1. 如果 li 有一萬個,會發生什麼事?
  2. 如果透過事件去增加 li,被新增的 li 被點擊時是否也會印出自己內容?

html

<ul id="menu">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
<button id="add-btn">add li</button>

js

let lis = document.querySelectorAll('#menu li')

lis.forEach(function (li) {
    li.addEventListener('click', function (e) {
        console.log(li.innerHTML)
    })
})

let addBtn = document.querySelector('#add-btn')

addBtn.addEventListener('click', function (e) {
    let menu = document.querySelector('#menu')
    let li = document.createElement('li')
    li.innerHTML = 'new li'

    menu.appendChild(li)
})

觸發流程

先抓取,再冒泡

事件氣泡

了解事件觸發流程後,針對氣泡特性,改善先前 nli 的事件綁定問題

let menu = document.querySelector('#menu')

menu.addEventListener('click', function (e) {
    let li = e.target
    console.log(li.innerHTML)
})

e.target 事件氣泡觸發元素

有沒有機會觸發到 ul ?

let menu = document.querySelector('#menu')

menu.addEventListener('click', function (e) {
    let li = e.target
    if (e.tagName == 'LI') {
        console.log(li.innerHTML)
    }
})

e.tagName 觸發元素標籤,統一為大寫

中斷冒泡

事件氣泡無論節點是否有處理,都會往上冒泡。如果不想氣泡繼續往上,使用 e.stopPropagation() 中斷冒泡

中斷預設行為

特定元素無需事件監聽就會進行預設行為,例如 a 元素會進行網頁跳轉。如想要禁止這種預設行為執行,使用 e.preventDefault() 中斷預設行為

html

<a href="https://www.google.com" id="link">Google</a>
let link = document.querySelector('#link')
link.addEventListener('click', function (e) {
    e.preventDefault()
    console.log(e.target.innerHTML)
})

單次計時器

在特定秒數後,執行特定函數,只執行一次

宣告

setTimeout(function, ms)

setTimeout(function() {
    console.log('Run after 1000ms')
}, 1000)

1s = 1000ms

取消

clearTimeout(timer)

timersetTimeout 回傳的計時器編號

let timer = setTimeout(function() {
    console.log('Run after 1000ms')
}, 3000)

clearTimeout(timer)

重複計時器

在特定秒數後,執行特定函數,重複執行直到取消為止

宣告

setInterval(function, ms)

setInterval(function() {
    console.log('Run after 1000ms')
}, 1000)

1s = 1000ms

取消

clearInterval(timer)

timersetTimeout 回傳的計時器編號

let timer = setInterval(function() {
    console.log('Run after 1000ms')
}, 3000)

clearInterval(timer)

練習

電子鐘

  1. 建立 UI
  2. 每秒更新該 UI 時間

時間取得方式

let d = new Date();
let hh = d.getHours();
let mm = d.getMinutes();
let ss = d.getSeconds();

綜合練習

TODO List

  1. 建立文字輸入匡,與一顆新增按鈕
  2. 建立列表區塊,每個項目前面加入 checkbox,如打勾則開項目顯示刪除線樣式。(text-decoration: line-through;)
  3. 按下新增按鈕後,將目前文字輸入框內容新增至下方列表