# 🗞 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)
```
印出結果:

## 觀念補充
### 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 選到按鈕了')
}
})
```
印出結果:

原因是透過 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

(二)使用 e.target.closest("li")

想了解更多關於 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 ,今天要實作刪除單筆/切換打勾:

重點提示:
* 監聽外層 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)