# 🗞 9/1(三) todolist 刪除單筆/切換打勾 ###### tags: `JavaScript 必修篇 - 前端修練全攻略` 本日對應章節為:todolist 待辦事項、陣列資料操作、箭頭函式基本寫法。 ## 觀念複習 ### findIndex([對應章節](https://courses.hexschool.com/courses/202011122/lectures/33931600)) 透過陣列方法 findIndex 可以獲取符合條件的索引值,如果找不到符合條件的索引值,就會回傳 -1 透過此方式,搭配 splice 方法,就可以刪除特定資料,參考程式碼如下: 假設下方是陣列的資料內容: ```jsx= const orders = [ { name: "艾草", id: 123456789 }, { name: "ViVian", id: 987654321 } ]; ``` 使用時需要留意型別,如果型別錯誤將找不到該筆資料 (HTML 內取出的皆為字串型別) ```jsx= // 透過 findIndex 找出符合『 id 為 123456789 』條件的索引值 let index = orders.findIndex((item) => item.id === 123456789 ); console.log(index) // 輸出結果為 0 ``` 以下是錯誤的寫法: >假設真的遇到需處理字串的型別 >建議使用雙等於 或是將資料轉換成數字後再做比較 ```jsx= let indexError = orders.findIndex((item) => item.id === "123456789" ); console.log(indexError)// -1 找不到 因為兩者型別不同 ``` 最終配合使用 splice 方法,透過回傳的索引值去刪除該筆資料即可。 ```jsx= orders.splice(index, 1); console.log(orders) ``` 印出結果: ![](https://i.imgur.com/5jHlrwI.png) ## 觀念補充 ### getElementById 當要獲取綁定 Id 的元素時,也可以透過 getElementById 來獲取,getElementById 的使用方式如下: HTML: ```html= <button id="addTodo" type="button">新增</button> ``` JavaScript: ```jsx= // 透過 getElementById 獲取 id 為 addTodo 的元素 const addTodo = document.getElementById('addTodo'); ``` 如果要選取其他的元素,也可以透過 querySelector 來實現,想更了解 getElementById 的使用方式,歡迎參考此篇[文章](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/getElementById)。 ### classList classList 可以拿來確認是否包含某個特定 class 類別,與透過 getAttribute("class") 的方式要符合全部 class 類別不同, 我們可以使用 Element.classList.contains('className'),來確認該 Element 是否存在某 className 類別。 完整範例如下: HTML: ```html= <button type="button" class="btn btn-outline-primary">按鈕</button> ``` JavaScript: ```jsx= //透過 querySelector 選取 class btn 這個元素 const btn = document.querySelector('.btn'); //給該按鈕註冊點擊事件 btn.addEventListener('click',(e)=>{ //方法一:透過 getAttribute("class") if (e.target.getAttribute("class") === "btn") { console.log("getAttribute 選到按鈕了"); } //方法二:透過 classList.contains //如果點擊到的元素 classList 內有包含 btn if(e.target.classList.contains("btn")){ console.log('classList.contains 選到按鈕了') } }) ``` 印出結果: ![](https://i.imgur.com/XcQ0gUZ.png) 原因是透過 getAttribute("class") 的方式選取 class 會回傳所有 class 同學可嘗試加入 console.log(e.target.getAttribute("class")) 就會發現輸出結果為 "btn btn-outline-primary" 而我們設置的判斷條件則是只需要判斷某一個 class 是否存在 此時就比較適合使用 classList.contains 方法判斷是否包含某一個特定樣式 想了解更多關於 classList 可以使用的方法,歡迎參考此篇 👉 [文章](https://developer.mozilla.org/zh-TW/docs/Web/API/Element/classList)。 ### closest 當在複雜 HTML 結構中想透過 e.target 選取某個 Element ,卻都只能選到它的子層時,可以透過 closest 去取到自己想要的 Element , 透過 closest 的方法,能很方便的取到自己想要的父層 Element ,範例如下: HTML: ```html= <ul class="list"> <li> <input type="text"> <span>123456789</span> <button type="button">按鈕</button> </li> </ul> ``` JavaScript: ```jsx= //透過 querySelector 選取 class list const list = document.querySelector(".list"); //註冊監聽 list 的點擊事件 list.addEventListener("click", (e) => { //單純監聽點擊到的元素本身 e.target console.log(e.target); //透過 closest 方法並於括號內透過字串形式的方式,放入想選取到的標籤名稱 console.log(e.target.closest("li")); }); ``` 分別點選 span 、 input 、 button 的印出結果如下: (一)單純使用 e.target ![](https://i.imgur.com/mEjShDV.png) (二)使用 e.target.closest("li") ![](https://i.imgur.com/ujEIVnC.png) 想了解更多關於 closest 可以如何使用,歡迎參考此篇 👉 [文章](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/closest)。 ## 問題 在實作前歡迎複習:[待辦刪除功能-前置解說](https://courses.hexschool.com/courses/202011122/lectures/33556185)、 [待辦刪除功能](https://courses.hexschool.com/courses/202011122/lectures/33556186)章節。 此為最終關卡任務,為了給同學更多實作空間,此次會縮減步驟指引,改以大方向提示的方式唷! 請同學 fork 此 👉 [ CSS 範本](https://codepen.io/hexschool/pen/KKmvpPP?editors=0010) 或使用昨天已實作新增功能之 todoList ,今天要實作刪除單筆/切換打勾: ![](https://i.imgur.com/2aD5GX7.png) 重點提示: * 監聽外層 ul 的點擊事件 * 取出點擊時該筆 li 的 id(此 id 需提前透過 `data-"自定義名稱"` 埋進渲染的字串內) * 刪除功能 * 確認點擊到的是打叉按鈕 * 找出點擊到的該筆資料的索引值 * 刪除該筆資料 * 切換打勾功能 * 確認點擊到哪筆資料(可透過 id 比對) * 點擊時新增 "checked" 屬性至 input checkbox 內(需提前埋進渲染的字串內) * 補充:input checkbox 的屬性 checked ,可以使 checkbox 呈現打勾 * 重新渲染 如果真的想不出來卡關了,也不要灰心,這裡有可愛的 Vtuber 艾拉的 👉 [todoList 教學](https://courses.hexschool.com/courses/202011122/lectures/34213327) 一天實作一點小功能,很快就完成囉!ヽ(✿゚▽゚)ノ 今天的範例投稿有兩份唷,在寫 Code 時,其實沒有所謂的標準解答,卡關時可以參考別人的程式碼,並融會貫通出自己的寫法唷! ## 回報流程 將答案寫在 CodePen 複製 CodePen 連結貼至下方作業投稿區中回報就算完成了喔! ## 作業投稿區(學員自行投稿) 1. [範例投稿一](https://codepen.io/jmkhsutp/pen/abwdpLv?editors=0011)、[範例投稿二](https://codepen.io/WangShuan/pen/poeLoyp?editors=0010)(可點此連結觀看解答) 2. [shoppingq](https://codepen.io/shoppingq/pen/LYLRGoj) 3. [詠銓](https://codepen.io/GGfish26/pen/wveGMjL?editors=1010) 4. [Yunei](https://codepen.io/Yunei/pen/eYRJMGw) 5. [佳鈴](https://codepen.io/zpyfpsxa/pen/ExXKyEx?editors=1010) 6. [Allen Lin](https://codepen.io/lcf7891/pen/WNOwQpJ?editors=0011) 7. [Jane Lin](https://codepen.io/as60160/pen/qBjbQrO) 8. [colinhyun](https://codepen.io/colinhyun/pen/wveGrLJ?editors=0011) 9. [中年大叔](https://codepen.io/adens123/pen/qBjbJwe?editors=1011) 10. [wind](https://codepen.io/wind7y/pen/eYRJaMr) 11. [LALA](https://codepen.io/bobee/pen/xxrVXZj?editors=0010) 12. [肉鬆](https://codepen.io/klrkicog/pen/ZEyWNmr?editors=1010) 13. [Izumi 泉](https://codepen.io/izumi-dev/pen/jOwqwgJ) 14. [小韭菜](https://codepen.io/jhang-jhe-wei/pen/PojzPOm) 15. [Sandy](https://codepen.io/Sandy_L/pen/BaZjxVX?editors=1011) 16. [Howard](https://codepen.io/yawdnhbm/pen/powyyVW) 17. [LMY](https://codepen.io/l_umei/pen/OJgNqgg) 18. [黃士桓](https://codepen.io/shr-huan-huang/pen/powbVXJ?editors=0011) 19. [AmberCYT](https://codepen.io/amberTing/pen/qBjbQmO?editors=1011) 20. [Rain Liao](https://codepen.io/billpop741/pen/mdmYewW) 21. [DoraYu](https://codepen.io/dora-yu/pen/ExXgRzQ?editors=1011) 22. [yojanni](https://codepen.io/unayo/pen/YzQWNGP?editors=1010) 23. [curry](https://codepen.io/Ted19851223/pen/eYRBqEb) 24. [皮皮](https://codepen.io/super-shrimp/pen/oNwBdJj?editors=1011) 25. [Hedy](https://codepen.io/babogooyache/pen/bGRpvjM) 26. [Wei](https://codepen.io/tartle120/pen/QWgKxMW) 27. [Margo](https://codepen.io/MargoMin/pen/vYZZeRK?editors=1011) 28. [SeanChang](https://codepen.io/seanchang7/pen/zYzZBRE?editors=1011) 29. [肉魚](https://codepen.io/zoechen13/pen/gORXYGY?editors=1011) 30. [Joe Kuo](https://codepen.io/alertislow/pen/wveeYzg) 31. [Joy Cheng](https://codepen.io/joycheng5432/pen/NWgXKmr?editors=0011) 32. [peter](https://codepen.io/peter_hung/pen/ZEyrVwN) 33. [Eileen](https://codepen.io/Eileen-Ching/pen/jOwZryy?editors=1010) 34. [Will](https://codepen.io/ncrdpepc-the-lessful/pen/abLNjOG?editors=0011) 35. [Sunny](https://codepen.io/Sunny0509/pen/xxXEwGX?editors=1011) 36. [Tina Yen](https://codepen.io/tlorfrnl-the-typescripter/pen/ExwKBao?editors=0011) 37. [BrunoYu](https://codepen.io/bruno-yu/pen/ExwmOBK?editors=0011) 38. [Jay](https://codepen.io/JayWang123/pen/KKZpKpv) 39. [庭瑋](https://codepen.io/wei_wu/pen/YzYVreR?editors=1111) 40. [int Huang](https://codepen.io/intHuang/pen/JjpKWzb) 41. [Peihan Wang](https://codepen.io/PeihanWang/pen/WNMpygy?editors=1111) 42. [Min](https://codepen.io/minnn7716/pen/KKQXNwp) 43. [Cliff](https://codepen.io/Cliff_hex/pen/qBopRmd) 44. [CookieSSS](https://codepen.io/sqhjikpa-the-selector/pen/KKoRaeX?editors=1011) 45. [Mimino](https://codepen.io/mimino/pen/qBYajQo?editors=0012) 46. [Alex](https://codepen.io/datsxzqg-the-selector/pen/bGMzpaL?editors=0011) 47. [qoq77416416](https://codepen.io/qoq77416416/pen/MWXjbdm?editors=1011) 48. [SASIMI](https://codepen.io/sashimi1327/pen/KKeeYoW) 49. [yunifer](https://codepen.io/yunifer1227022/pen/mdGeJLb?editors=1111) 50. [Eden](https://codepen.io/Eden-C/pen/eYLbZRY) 51. [wei](https://codepen.io/Wei-the-sasster/pen/RwOgqyL?editors=1011) 52. [yuhao](https://codepen.io/tqdtaouh-the-styleful/pen/GgRvxJp)