---
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>