---
# System prepended metadata

title: 範例_充電站
tags: [六角學院_JavaScript 必修篇 - 前端修練全攻略]

---

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