- HW1 明天做,眼睛酸
參考範例:hw2 FAQ 頁面(請先寫完作業再看)
1'30" 開始切版
9'30" 收縮功能
12'35" 點擊事件
document
.querySelector('.questions')
.addEventListener('click', function(e) {
const clickArea = e.target.closest('.q-block')
if (clickArea) {
clickArea.classList.toggle('q-block--hide')
}
})
// 先選到 questions 這個 class 的元素
// 監聽 questions 裡面的 click 事件
// 給一個變數叫做點擊範圍
// e.target 觸發事件的元素(點擊的地方)
// .closest 從當前元素開始,往回到第一個祖父元素
// e.target.closest('.q-block') 在 q-block 裡面發生點擊事件,
// 就從自己本身開始找,直到第一個祖父元素
// classList.toggle(),有就刪除,沒有就加回來(像是電燈開關吧,
// 按一下開燈,再按一下關燈)
// 如果「有偵測到點擊事件,就把留言打開或關閉」
參考資料:
- 在 RWD 那裡調半天,不太懂怎麼調,應該會有一個固定模式的,像是 320, 768, 1024 有四種組合之類的?
參考範例:hw3 todo list(請先寫完作業再看)
0 - 3'30": html
3'33": 排版
7'11" - 10'25": 新增功能
10'29" - 15'51": 過濾輸入字串,跳脫 js escape
- 跟資安有關,在 W11, W12 會學到
- 特別注意輸入字串的樣式,像是如果輸入標籤之類的,也會正確解讀為「文字」而不是標籤,跟那個網址後面的 & 有關,關鍵字「encode html」
15'50" - 18'10": appendChild 的運作模式
- 對節點使用 appendChild 時,會對節點做移動,而不是複製;要真的複製的話,要用 cloneElement or Node.cloneNode(),我現在還不是很清楚要怎麼做,先放著。
18'38" - 22'48": 刪除功能
22'48" - 26'50": check/uncheck
- classList.toggle() 不適用,因為有分 checked / unchecked
27'00": 重點在於事件代理人
- 完全想不到要注意 "escapeHtml"
- 也沒有注意到「有輸入才能新增」 "if (!todolist) return"
- 刪除功能裡面的 target 不知道要取什麼名字更好?
// 當點擊新增按鈕時,取得 input 裡面的資料內容,並新增一個待辦清單欄位
// 新增功能
document
.querySelector('.create')
.addEventListener('click', function() {
const todolist = document.querySelector('.input-todo').value;
if (!todolist) return
const addNew = document.createElement('div')
addNew.classList.add('todo')
addNew.innerHTML = `
<input class="check" type="checkbox">
<div class="todo-list">${escapeHtml(todolist)}</div>
<button class="delete">x</button>
`
document.querySelector('.content').appendChild(addNew)
document.querySelector('.input-todo').value = ''
})
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'")
}
// 刪除功能
document
.querySelector('.content')
.addEventListener('click', function(e){
const target = e.target
if (target.classList.contains('delete')) {
target.parentNode.remove()
return
}
// 完成/未完成功能
if (target.classList.contains('check')) {
const chk = target.parentNode.classList
target.checked?chk.add('done'):chk.remove('done')
} // eslint 大概不給過吧
// if (target.classList.contains('check')) {
// if (target.checked) {
// target.parentNode.classList.add('done')
// } else {
// target.parentNode.classList.remove('done')
// }
// }
})
- 學習重點就是:
- 選對元素
- 加監聽器
- 知道要用哪個函式: https://htmldom.dev/ 超棒網站
- target.classList.contains()
- target.parentNode.remove()
- add()
- .checked