--- tags: 六角學院_JavaScript 必修篇 - 前端修練全攻略 --- 範例_充電站 === <iframe height="300" style="width: 100%;" scrolling="no" title="本章節充電站 Code 範例" src="https://codepen.io/hexschool/embed/oNYPPPx?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/hexschool/pen/oNYPPPx"> 本章節充電站 Code 範例</a> by hexschool (<a href="https://codepen.io/hexschool">@hexschool</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 0.如何內嵌codepen --- 1. 點擊在 Fork 旁邊的 Embed 2. 點選 Inframe , 把code 貼到 HackMD 裡 1.將資料顯示出來 --- ### HTML 1. 新增 `h2{資料顯示}` 2. 新增 `ul.list>li{hello}` ==補充:[Emmet語法](https://pjchender.blogspot.com/2016/07/emmet.html)== ```htmlmixed= <h2>資料顯示</h2> <ul class="list"> <li>hello</li> </ul> ``` ### JS 1. 創建 `data` 變數,並輸入資料(格式:陣列內包含多個物件) 2. 操作 DOM 時,通常會用 `const` ,比較不容易不小心改變值 3. 將初始化變成一個 `function` 1. **==使用 `document.querySelector` ,選擇器要用對,常忘記 `.`==** 2. 創建空字串 `str` ,記得賦值,不然會有 `undefined` 在列表第一處 3. `.forEach` 用 item 我感覺比較好,因為很常要 `.value`,如果照VS Code裡的寫會變成`value.value` 4. **==`content` 裡面的是整個標籤語言,常忘記打`<li> </li>`==** 5. 使用 `.innerHTML` 改變裡面的標籤語言 4. 呼叫初始化函數 ```javascript= // 資料 let data = [ { name: "充電站1", charge: "免費" }, { name: "充電站2", charge: "免費" }, { name: "充電站3", charge: "投幣式" }, { name: "充電站4", charge: "免費" }, { name: "充電站5", charge: "投幣式" }, ]; // 預設載入函式 const list = document.querySelector(".list"); function init() { let str = ""; data.forEach(function (item, index) { let content = `<li>${item.name} , ${item.charge}</li>`; str += content; }); list.innerHTML = str; } init(); ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD專用" src="https://codepen.io/jason60810/embed/XWRQoYR?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/XWRQoYR"> HackMD專用</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 2.篩選出點擊的資料 --- ### HTML 1. 新增 `div.filter>input:b[value="全部"]*3` ```htmlmixed= <div class="filter"> <input type="button" value="全部" /> <input type="button" value="免費" /> <input type="button" value="投幣式" /> </div> ``` ### JS 1. 創建 `filter` 存入 DOM 2. 使用 `.addEventListener` 監聽點擊事件 1. 如果 `e.target.value === undefined` 代表點到不是按鈕的其他 `div` 區域,並 `return` ,==如果沒有 `return` 會讓整個資料空白== 2. 創建空自串 `str` 3. 使用 forEach 和條件式,顯示按鈕點選的內容 4. 使用 `.innerHTML` 改變裡面的標籤語言 ```javascript= // 篩選器邏輯 const filter = document.querySelector(".filter"); filter.addEventListener("click", function (e) { if (e.target.value === undefined) { console.log("又點又點"); return; } let str = ""; data.forEach(function (item, index) { if (e.target.value === "全部") { str += `<li>${item.name} , ${item.charge}</li>`; } else if (e.target.value === item.charge) { str += `<li>${item.name} , ${item.charge}</li>`; } }); list.innerHTML = str; }); ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD_充電站_2" src="https://codepen.io/jason60810/embed/dyWLaex?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/dyWLaex"> HackMD_充電站_2</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 3.新增資料 --- ### HTML 1. 新增 `h2{新增資料}` 2. 新增 `input.stationName[placeholder="充電站名稱"]+(select.stationCharge>opt*2)+input:b.btn` 1. `option` 裡面要放東西,下拉式選單才會有東西 ```htmlmixed= <h2>新增資料</h2> <input type="text" class="stationName" placeholder="充電站名稱" /> <select class="stationCharge"> <option value="免費">免費</option> <option value="投幣式">投幣式</option></select ><input type="button" value="儲存" class="btn" /> ``` ### JS 1. 創建 `stationName` `stationCharge` `btn` 存入 DOM 2. 監聽 `btn` 1. 創建 `obj` 給空物件 2. 使用 `.屬性 = 內容`,新增物件屬性和內容 3. 使用 `push` ,將新物件加進 `data` 中 4. 使用 `init` 重讀 `data` 5. 把剛才輸入的東西清空,`.value = ""` 6. 指定預設選項,`.value = "免費"` ```javascript= // 新增邏輯 const stationName = document.querySelector(".stationName"); const stationCharge = document.querySelector(".stationCharge"); const btn = document.querySelector(".btn"); btn.addEventListener("click", function (e) { let obj = {}; obj.name = stationName.value; obj.charge = stationCharge.value; data.push(obj); init(); stationName.value = ""; stationCharge.value = "免費"; }); ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD_充電站_3" src="https://codepen.io/jason60810/embed/dyWLagb?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/dyWLagb"> HackMD_充電站_3</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 4.刪除資料 --- ### JS 1. 將之前 `<li>${item.name} , ${item.charge}</li>` 都改成 `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>` 3. 使用 `.addEventListener` 監聽點擊事件 1. 如果 `e.target.getAttribute("class") !== "delete"` 代表點到不是按鈕的其他 `ul` 區域,並 `return` ,==如果沒有 `return` 會從頭開始刪== 2. 創建 `num` 3. 使用 `e.target.getAttribute("data-num")`,抓取每個刪除按鈕的 index 4. 使用 `.splice(從哪開始刪,刪幾個)` 5. 重新讀過 `data` ```javascript= //刪除資料 list.addEventListener("click", function (e) { if (e.target.getAttribute("class") !== "delete") { console.log("為什麼不幫我點按鈕極靈"); return; } let num = e.target.getAttribute("data-num"); data.splice(num, 1); init(); }); ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD_充電站_4" src="https://codepen.io/jason60810/embed/qBmzVPe?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/qBmzVPe"> HackMD_充電站_4</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 5.解決在篩選狀態下刪除會跳回全部的問題 --- ### JS 1. 創建變數 `status` 儲存現在篩選按鈕的狀態,預設"全部",記得要放在前面,不然要呼叫時會找不到這個變數 2. 在點選篩選按鈕(`e.target.value`)時,將按鈕值更新至 `status` 3. 在預設載入函式增加參數 `status` ,判斷列印 `data` 時要怎麼印 4. 後面有呼叫 `init()` 的地方,都改成 `init(status)` ```javascript= // 儲存篩選狀態 let status = "全部"; // 預設載入函式 const list = document.querySelector(".list"); function init(status) { let str = ""; data.forEach(function (item, index) { if (status === "免費" || status === "投幣式") { if (status === item.charge) { let content = `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; str += content; } } else { let content = `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; str += content; } }); list.innerHTML = str; } init(status); // 篩選器邏輯 const filter = document.querySelector(".filter"); filter.addEventListener("click", function (e) { if (e.target.value === undefined) { console.log("又點又點"); return; } let str = ""; data.forEach(function (item, index) { if (e.target.value === "全部") { str += `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; } else if (e.target.value === item.charge) { str += `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; } }); list.innerHTML = str; status = e.target.value; }); ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD_充電站_4" src="https://codepen.io/jason60810/embed/dyWxerR?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/dyWxerR"> HackMD_充電站_4</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 6.簡化程式碼_V1 --- ### JS 1. 創建函數代替 `.forEach` 印出的地方,有兩種印法,全部都印,只印篩選按鈕點的 ```javascript= // 印出資料函式; function showDataAll(obj) { let str = ""; obj.forEach(function (item, index) { str += `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; }); list.innerHTML = str; } function showDataFilter(obj, condition) { let str = ""; obj.forEach(function (item, index) { if (condition === item.charge) { str += `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; } }); list.innerHTML = str; } // 預設載入函式 const list = document.querySelector(".list"); function init(status) { data.forEach(function (item, index) { if (status === "免費" || status === "投幣式") { showDataFilter(data, status); } else { showDataAll(data); } }); } init(status); // 篩選器邏輯 const filter = document.querySelector(".filter"); filter.addEventListener("click", function (e) { if (e.target.value === undefined) { console.log("又點又點"); return; } let str = ""; if (e.target.value === "全部") { showDataAll(data); } else if (e.target.value === "免費" || e.target.value === "投幣式") { showDataFilter(data, e.target.value); } status = e.target.value; }); ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD_充電站_5" src="https://codepen.io/jason60810/embed/mdmNKao?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/mdmNKao"> HackMD_充電站_5</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> 7.簡化程式碼_V2 --- ### JS 1. 使用 `arguments.length` 計算參數數量,產生類似 overload 效果,並將所有`showDataAll()` `showDataFilter()` 代替成`showData()` ```javascript= // 印出資料函式; function showData(obj, condition) { let str = ""; let argumentsNum = arguments.length; obj.forEach(function (item, index) { if (argumentsNum === 1) { str += `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; } if (condition === item.charge) { str += `<li>${item.name} , ${item.charge}<input type="button" class="delete" data-num="${index}" value="刪除" /></li>`; console.log(arguments.length); } }); list.innerHTML = str; } ``` ### 小試身手(可編輯,重新整理頁面可以還原) <iframe height="300" style="width: 100%;" scrolling="no" title="HackMD_充電站_5" src="https://codepen.io/jason60810/embed/jOmgKRr?default-tab=html%2Cresult&editable=true" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/jason60810/pen/jOmgKRr"> HackMD_充電站_5</a> by jason (<a href="https://codepen.io/jason60810">@jason60810</a>) on <a href="https://codepen.io">CodePen</a>. </iframe>