---
# System prepended metadata

title: 4/12 線上 Slack 助教
tags: [JS 直播班 - 2021 春季班]

---

---
tags: JS 直播班 - 2021 春季班
---

# 4/12 線上 Slack 助教

## 今日輪班助教時間

SONYKO：4/12（一）
早上 9:00 - 早上11:00，下午 1:00 -下午 5:00


## 發問規範

老師助教同學們好，**這是我的 Codepen**，我**原本預期**「JS 第 8 行會出現數字 8」，**但卻出現**「預期外的結果是 0」，想問下問題出在哪裡？

## 注意

1. 請各位先到 Slack 上將問題放在助教服務內的 thread，如圖
 ![](https://i.imgur.com/nHE3sOx.png)
2. 遵循以上的發問規範以便助教查看問題，不可直接貼上網址而沒有說明文字或者只提供截圖
3. 助教會依照 Slack 上的順序回覆問題
4. 以下問題區塊只能由助教自行增加
5. 助教會將回覆寫在下方問題區塊

## 問題
🎀　<font color="#e5b3cc">這裡只能由助教自行增加問題，請大家將問題放在 thread 上　</font>💕

 
<font color="#e5b3cc">1. **Dora**　🍒　</font>
老師助教同學們好，這是我的 CodePen，
關於第九周的教學，
我原本預期「JS 第 8 行到第14行」可以取得產品列表，但console卻出現404(找不到檔案)，
但我把js code改為第15行到20行,axios就可以取到productData，
但我看js code第8-14行與js code第15行到20行都一樣阿，請問我到底哪裡出問題呢?
謝謝!
> 助教回覆：
帶入 axios 的網址不能使用單引號， 因為裡面有帶變數 ${api_path}。
反引號 + ${api_path} 屬於樣板字面值的寫法， 若要使用單引號只能這樣寫：
> ```
> axios.get('https://hexschoollivejs.herokuapp.com/api/livejs/v1/customer/'+ api_path +'/products')
> ```
> 詳細可以參考[文章](https://wcc723.github.io/javascript/2017/12/22/javascript-template-string/)。 有問題也歡迎再提出哩！
---
<font color="#e5b3cc">2. **方文文**　🍒　</font>
我看助教在寫卡片渲染的function時，都會另外設一個變數str先存進來，再塞給  卡片DOM.innerHTML，如下：
```
// 渲染產品資訊畫面
        function renderProduct(product) {
            let str = '';
            product.forEach((item) => {
                str += `
      <div class="col-6 mb-3">
      <div class="card">
        <img src="${item.images}" class="card-img-top productImg" alt="${item.title}">
        <div class="card-body">
          <h5 class="card-title"><strong>標題:</strong> ${item.title}</h5>
          <p class="card-text"><strong>種類:</strong> ${item.category}</p>
          <p class="card-text"><strong>原始價格:</strong> ${item.origin_price}</p>
          <p class="card-text"><strong>售價:</strong> ${item.price}</p>
          <p class="card-text"><strong>描述:</strong> ${item.description}</p>
        </div>
      </div>
    </div>
    `            })
            productList.innerHTML = str;
        }
```
我是直接把html塞給productList.innerHTM，如下：
```
// 卡片渲染到畫面上
function renderCard(){
    productDetailapiData.forEach(function(item,i){
      // console.log(cardInfo)
      // console.log(item,i)
      cardInfo.innerHTML +=`<div class="card">
        <img src="${item.images}" class="card-img-top productImg" id="productImg" alt="產品圖片">
        <div class="card-body">
          <h5 class="card-title"><strong>標題:</strong> <span id="productTitle">${item.title} </span></h5>
          <p class="card-text"><strong>種類:</strong> <span id="productCategory">${item.category} </span></p>
          <p class="card-text"><strong>原始價格:</strong> <span id="productOrgPrice">${item.origin_price} </span></p>
          <p class="card-text"><strong>售價:</strong> <span id="productPrice">${item.price} </span></p>
          <p class="card-text"><strong>描述:</strong> <span id="productDetail">${item.description} </span></p>
        </div>
        <input type="button" value="加入購物車" class="cartBtn" data-num="${item.id}">
      </div>`
    })
}
```
兩者都可以實現一樣的功能，只是想問：
1. 什麼要多加一個str?好處是甚麼?
2. 我的寫法會有甚麼樣的風險或缺點嗎?

> 助教回覆：
> 1 和 2 一起回答～
有沒有使用 str 的差異可以參考[這個範例](https://codepen.io/s_syoujyo/pen/OJWQZeO)。 
以上面例子來說， 如果直接塞給 container ， 原先有的資料不會被覆蓋。
若宣告 str 再 innerHTML ， 原先有的資料才會被蓋掉， 兩者差異在這邊哩。
>
> 假如你想塞的地方原本沒有資料的話， 兩著的寫法可以說是一樣， 也沒有什麼差異。 假如你要塞的地方原本有資料， 那只接用 innerHTML += 的方式可能會沒辦法將原有的資料覆蓋掉。
> 
> 以上回答若有不懂的地方 歡迎再提問哩～
---
<font color="#e5b3cc">3. **方文文**　🍒　</font>
我看助教用axios再摳API的時候，都會加上catch
想問一下加上去有甚麼好處?
```
// 摳API- 產品列表A
function getProduct() {
  let url = `${baseUrl}/api/livejs/v1/customer/${api_path}/products`;
     axios.get(url)
     .then(function (res) {
        productData = res.data.products;
        renderProduct(productData);
     })
     .catch(function (error) {
        console.log(error);
     })
  }
```
> 助教回覆：
> .catch 是接收錯誤訊息時用的， 因為我們沒有辦法確定每隻 API 是否都能正確串接。 
> 有時候可能沒有寫 catch 、但還是能接收到 404 或 500 這種錯誤， 那是因為這種錯誤屬於 "無法執行" 的狀態， 並非 API 回報的錯誤。
> 
>後端可以設定 catch 要回傳的內容， 由於我們不確定這隻 API 到底會以什麼形式報錯、所以建議都要加上 catch 。
>
>catch 這邊的接收的是後端回傳的「特定的內容」， 像是有的 API 可能就會把此帳號已被使用放在 catch 的地方哩。
>
>以上回覆不知道同學有沒有理解，
如果還是覺得很模糊、 也歡迎再提出問題唷。
---
<font color="#e5b3cc">4. **方文文**　🍒　</font>
我正在補寫4/5的每日作業時遇到問題
想問一下怎麼用 test-cors.org 判斷資料是否可以不需驗證直接使用(Access-Control-Allow-Origin: *)
以這支API為例，我預期把資料裡面最上面這個註解掉的網址，打在text.cors.org的Request Headers或是Request Content，就可以在下方的result看到結果，但是出現以下的結果，一連試了幾隻都沒有顯示"Access-Control-Allow-Origin"這個欄位@@
```
age: 1
cache-control: public, max-age=600
content-encoding: gzip
content-length: 2539
content-type: text/html
date: Mon, 12 Apr 2021 03:43:52 GMT
etag: "1rO4KQ"
expires: Mon, 12 Apr 2021 03:53:52 GMT
server: Google Frontend
x-cloud-trace-context: 62b03d3e0241134e2046a32de3f32329
```
想請教一下正確的用法?
> 助教回覆：
> 阿... ! 同學要把網址貼到這邊查哩！
>  ![](https://i.imgur.com/cCi7qWU.png)
>  另外網站會回傳 XHR status: 200 就表示可以撈取資料。
>  同學可以再複習一下第 8 週影片上半部 44 分左右的地方～ 
>  
>  關於 "Access-Control-Allow-Origin" 這個欄位是我們開啟 API 網址，按右鍵檢查 > Network > Headers > Response Headers 裡面會回報的。 這個網站的 Results 不會回傳喔～
>  
>  以上回答若有問題歡迎再發問哩。


---
<font color="#e5b3cc">5. **咖哩**　🍒　</font>
助教好~想請問有關 getAttribute 抓取class問題
問題如圖下所表示
![](https://i.imgur.com/lnk75KX.png)
假設我的 html 有複數的 class ==> 
```
class="material-icons delete mb-6"
console.log(e.target.getAttribute("class"));
```
我用 getAttribute 抓取class
會回傳給我一堆的 class 字串 // material-icons delete mb-6
當我用判別是去判斷有無存在的 “delete” 時候
只能整個全寫？？ 還是有更好的方式去抓取 "只選到 delete"
 ```
if (e.target.getAttribute("class") !== "delete") {
      return;
  }
```
> 助教回覆：
> 這邊提供同學一個方法，[請參閱](https://codepen.io/s_syoujyo/pen/eYgVKYw?editors=0011)。
> 語法為 .match 。多用來查詢有無相符字串。
> 同學的問題不知道能不能用它解決， 參考一下哩～
> 
> 若有不懂的地方歡迎再提出唷！
---
<font color="#e5b3cc">6. **王懷英**　🍒　</font>
老師助教同學們好，這是我的 [CodePen](https://codepen.io/huaiying/pen/qBRPbVm) 。
我在練習第五周主線任務的篩選邏輯，本來預期「JS 第 132 行會出現數字 篩選後的筆數」，但卻沒有任何反應，想問下問題出在哪裡呢？ 謝謝^^
> 助教回覆：
> 程式碼 132 行帶入 data.length ， 但這邊的 data 是指外面那個陣列。 因此不管怎麼篩選， 數量都會是外面那個陣列的長度歐。 
> 可以試試創造一個新的陣列， 將符合的物件 push 到新的陣列， 再取那個新陣列的長度。
> 以上建議同學可以試著修改看看歐。 順便附上[參考](https://codepen.io/s_syoujyo/pen/oNYRKBz)（程式碼 104 行的地方） 。
> 有問題歡迎再發問哩～

---
<font color="#e5b3cc">7. **Valerie**　🍒　</font>
老師助教同學們好，這是我的 [CodePen](https://codepen.io/vicky-chang/pen/poRdMyO)，
1. 我原本預期「JS 第 98 -114行可以執行刪除特定的購物車資料」，但點選時卻出現「加入購物車對話框」，想請問問題出在哪裡？
2. 另外在js 第 85 行的執行清空購物車，點選刪除所有購物車項目後，需要重新整理才能刪除，請問該如何不重新整理也能在畫面上直接刪除呢?
再麻煩助教，謝謝!!
> 助教回覆：
> 1. 由於刪除和新增都是渲染出來的 HTML， 因此刪除也要像新增購物車一樣，去監聽 productList 。由於監聽時少了判斷，以新增舉例，我們沒辦法知道目前點到是哪個按鍵，這邊建議補上判斷。 舉例： 我在渲染按鈕加了一個 addcart 的 class ， 接著在新增函式內寫 : 
> ![](https://i.imgur.com/VPTPcQd.png)
>
> 這樣才能正確選到加入購物車按鈕。 
> 刪除也是同樣的寫法， 一樣監聽一整個 productList 再去判定我點到的是不是刪除按鈕， 應該就會正常了。
> 
> 2. 把 getCartList(); 加進去就會正常哩。因為 renderList 只有渲染， 並無重新取得資料。 要刪除後取得新的資料再渲染， 才會正常的呈現。
>
> 以上建議供同學參考。 若有問題歡迎再提出來唷～ 

---
<font color="#e5b3cc">8. **carol liao**　🍒　</font>
老師助教同學們好，這是我的 [Codepen](https://codepen.io/yaxuan/pen/xxgXKqj)，請問怎麼把訂單日期，轉換成 2021/4/12 這樣的格式呢？不太了解做法
> 助教回覆：
> 這邊提供同學轉換時間格式的語法：
> https://codepen.io/s_syoujyo/pen/qBRxybx
> 助教自己也是每次要轉都要查很久XDDD
> 可以筆記下來哩～

---
<font color="#e5b3cc">9. **獵人**　🍒　</font>
老師助教們好：
請問最終作業後台的訂單日期為1970/01/20這樣是對的嗎?還是我轉換錯了呢?
JS第70.71行中
https://codepen.io/tyriel/pen/XWpZYmr
> 助教回覆：
> 程式碼第 70 行， 要改成 `var ticks = item.createdAt*1000;` 才會得到正確的時間唷！
> (( 助教也被 1970 困惑到 XDDDD

---
<font color="#e5b3cc">10. **Jordan_Tseng**　🍒　</font>
老師助教同學們好，想問這個驗證的網站上這幾個部分是怎麼閱讀的，有點看無，本來要寫驗證email，後來找到六角的鐵人文章才知道怎寫。另外想問驗證電話號碼我想使用equality，但是一直無法驗證成功，是因為是國外電話號碼格式嗎？，這是我的[code](https://github.com/Jordan-TTC-Design/hex-2021spring-finalwork/blob/871ecda52c0374ea59eff2a60cf4deb720730fd0/shop.js#L275)，我暫時先槓掉。
> 助教回覆：
> equality 應該是用來驗證有沒有重複用的 >A < ??! 像密碼要打兩次的那種。
> 可以參考葉子助教的[文章](https://ithelp.ithome.com.tw/articles/10209129)，寫得很詳細哩。 
> 裡面也有提到 equality 的用法， 但主要像上面說道、是用來驗證確認密碼用的。 
> 
> 不知道有沒有幫同學解到惑， 若沒戳到點再麻煩同學補充說明哩。

---
<font color="#e5b3cc">11. **Fred Chang**　🍒　</font>
老師助教同學們好，我總共有3個問題想要請教:
1. 4/5每日任務的第一小題，[這個API連結](https://iplay.sa.gov.tw/odata/GymSearch?$format=application/json;odata.metadata=none&City=%E9%AB%98%E9%9B%84%E5%B8%82&GymType=%E6%A3%92%E7%90%83%E5%A0%B4&Latitude=22.6239746&Longitude=120.305267)助教給的答案是可以透過瀏覽器端讀取，雖然使用test-cors確認是可以沒錯，但在Response Header始終找不到老師所說的Access-Control-Allow-Origin:* ，想請教原因為何。

2. 這是我最終作業的前台[Codepen](https://codepen.io/fred8196/pen/bGgLjMV?editors=1010)，在第151-159行將刪除單一和全部品項合併監聽，兩個功能皆可能正常執行，但想請問第156行的  else if (e.target.getAttribute("class") === "material-icons" || "deleteOne") 是否有方法只取class 的第二個名稱來判斷呢? 因為用material-icons來判斷語意上似乎不太正確。另外，即使可以成功刪除單一品項，但點擊購物車清單其他任何位置，也會執行156行else if 內的程式，這樣的話是不是其實這個判斷根本有問題? 想了解原因以及如何改寫。

3. 承上題，要先麻煩助教把151-159行註解掉，然後打開162-176行，這邊162-168行的問題和第2題一樣，主要是想請教169-176行，這邊我原本想把刪除全部的功能拉出來單獨監聽，但似乎在宣告DOM時就是null了，我有想過是不是因為非同步問題，在購物車列表尚未渲染完成就宣告DOM所以抓不到，但如果是這樣為什麼第53行宣告shoppingCart又是可以抓到的呢? 有什麼寫法可以解決這種問題嗎?
以上3點還請助教協助解惑，感謝！ 
> 助教回覆：
> 1. 助教這邊看也是沒有 Access-Control-Allow-Origin:* ， 應該是那隻 API 的問題 OAQQQ 。 但因為用 test-cors 確認可以所以可以撈到。 
> 
> 2. 用 target.getAttribute 不管什麼屬性都可以抓來監聽， 所以今天你想另外設 id 或是再塞一個 data-set 來做判斷也是可以。另外語意上怪怪倒是真的XDDD
> 至於點擊其他位置也會執行的判斷有寫錯是因為：
> ```javascript
> else if (e.target.getAttribute("class") === "material-icons" || "deleteOne")
> ``` 
> 應該要寫成： 
> ```javascript
> else if (e.target.getAttribute("class") === "material-icons" || e.target.getAttribute("class") === "deleteOne")
> ```
> `|| "deleteOne" `會變成 `|| true` 來判斷， 所以才會不管怎麼點都會跳 alert 。
> 
> 3. 這邊純粹是 class 名稱打錯喔 XDDD 是 .discardAllBtn 
> 改完就不會跳錯了。
> 
> 以上回覆若有問題歡迎再發問哩！


---
<font color="#e5b3cc">12. **peter.chen1024**　🍒　</font>
我想請問4/5號的每日任務，https://hackmd.io/Nqjs-2nARbCSC9JTyf-vNQ?view
第一題:「全球運動場館資訊網」: 網址
我用瀏覽器的network看responseHeader並沒有看到 `Access-Control-Allow-Origin: *`
但是用text-cors打可以得到200，請問這個API算是可以跨網域讀取的嗎QQ
補充:我用axios.get直接打有讀取到資料，所以不一定要顯示`Access-Control-Allow-Origin: *`  也可以做跨網域讀取嗎? 

> 助教回覆： 
> 通常要發出 Request 的時候才會回傳結果。 
> 由於每個網址類型不同， 像這個網址就只是被打開而已， 並沒有發出請求。 如果使用 Codepen 實作應該可以看到 `Access-Control-Allow-Origin: *` 的標示。 
> test-cors 會幫你實測發出請求， 所以使用它來看有沒有回傳 200 會比較準確哩。
---
<font color="#e5b3cc">13. **Jordan_Tseng**　🍒　</font>
老師助教同學好，[這是我的扣](https://github.com/Jordan-TTC-Design/hex-2021spring-finalwork/blob/d46495c36059e4967fa28af57196846c4fbd940b/admin.js#L144)，我本來想用三元運算子來做判斷說如果訂單狀態是未處理就改成已處理，已處理就改未處理，我這樣寫改成已處理可以成功，但是改回未處理就是無法，無法把changeStatus改回false，我後來想說直接寫成if判斷式，但是還是不行。
> 助教回覆：
> 這邊的 nowStatus 是字串，所以沒辦法變換。 
> 可以使用 console.log(typeof(nowStatus)) 會得到 string 。
> 把它轉換成布林值應該就會動了，同學再試試看喔～
---
<font color="#e5b3cc">13. **洋蔥**　🍒　</font>
老師助教同學們好，這是我的 [CodePen](https://codepen.io/mikeyam/pen/ZELrVPw?editors=1011)（請附上連結），
問題一：
我對於「JS 第 2 行 `document.querySelectorAll('[data-title]'`)」不太了解，跟每日任務4/7 範例對不太上，不太懂為什麼範例1，要加入[0]，而我寫的卻不用 ？
// 1
`document.querySelectorAll('[data-title]')[0]`;
// 2
`document.querySelector("[data-title='信箱']")`;
問題二：
上方這兩個取dom方式，在業界上常用嗎？
都會用在什麼地方？ 
> 助教回覆：
>1. 關於「不太懂為什麼範例1，要加入[0]，而我寫的卻不用」：
這邊範例是以 "選取到信箱" 為例， 所以才加上 [0] 。因為 querySelectorAll 得到的會是類陣列～ 
>
>2. 關於業界上常不常用比較沒什麼關聯， 
>因為他本身就是一個可以取用到 DOM 的方法， 看個人習慣怎麼使用而已。
>就有點像有人喜歡用 querySelector 有人喜歡用 getElementById ，除非你的公司有規定你要用哪個寫（通常是不會）， 就只是習慣的問題。
>
> 以上回答若有疑問歡迎再提出哩～

---
<font color="#e5b3cc">14. **Hsin**　🍒　</font>
助教好，這是我的[codepen](https://codepen.io/hsinhui/pen/VwPrddG?editors=0010)，想請問我放在258行做為送出表單後要清空購物車的程式碼，如果放在253行後面就無法正常運行? 我的邏輯是成功送出訂單後再清空購物車，麻煩助教了，謝謝 
> 助教回覆：
> 以這隻 API 來說， 送出訂單不需要再執行清空購物車的動作。
> 因為 API 將購物車內產品提交後， 購物車會是空的。 
> 因此這邊是要重新 get 購物車資料， 而非清空購物車哩！ 

---
<font color="#e5b3cc">15. **雅帆**　🍒　</font>
助教好，我想請問關於一個函式參數的寫法問題。
昨天的[每日任務題目程式碼](https://codepen.io/znlcgmgk/pen/BapJVve?editors=1011)的 JS 第 13 和 19 行助教有帶參數進去，我不了解的點是 JS 第 6 行不是已經有宣告 productData 空陣列了，為什麼 JS 第 13 和 19 行 還要帶變數？
因為我自己都習慣寫沒有代參數的寫法，也一並[附上程式碼](https://codepen.io/yafanchung/pen/zYNPaOB?editors=1010)
有點不太會使用參數，不曉得還是我觀念哪邊有誤？再請助教指教，感謝！ 
> 助教回覆：
> 助教一開始也很不會帶參數 OAQ 
> 關於昨天的每日任務 13 和 19 行， 首先要先分清楚一下參數和變數是不一樣的東西哩 >A < ; 
> ![](https://i.imgur.com/zA15FcE.png)
> 
> 19 行小括號裡為參數， 是可以隨意命名。
> 13 行為叫用函式， 此時就要帶入正確的變數名稱進去。
> 
> 同學的寫法也沒有問題， 但這樣就會產生很多重複的程式碼。
> 假如做篩選， 我要渲染篩選完的陣列的話， 是不是就要再用新的陣列去跑一次 forEach 渲染 HTML 結構 ？ 
> 
> 但當今天有參數可以帶的話， 我只要寫好一個渲染用的函式， 挖空（放陣列）當我要用到時再呼叫他（參數帶入陣列變數）， 就可以省去很多重複的程式碼。 
> 以第五週作業為例， 同學可以比對 [無參數程式碼](https://codepen.io/yen-hong-kuo/pen/NWbQzdo?editors=0010) 及 [有帶參數程式碼](https://codepen.io/s_syoujyo/pen/oNYRKBz) 的差異。
>
> 帶參數可能要慢慢習慣， 但同學可以先思考， 如果寫 code 該怎麼樣去縮減程式碼、 哪些可以寫成參數， 慢慢就會知道該怎麼寫哩～
> 
> 若有不懂的地方也歡迎隨時提出唷！

---
<font color="#e5b3cc">16. **moitw**　🍒　</font>
助教好～想請問關於validateJs的問題。
我的[codepen](https://codepen.io/tsuifei/pen/JjEpmyR?editors=1011)，當點擊新增套票的按鈕時，會去觸發`checkInputs`這支函式，檢查表單個欄位也似乎沒有問題，唯獨最後一個欄位245-252行的位置，限制不能留白且不可超過100字元，但是這欄即使填了文字，或超過100字元，都會重複跳出此欄的第一個約束條件“是必填欄位” ，會有可能出現的問題可能是哪裡呢？
還有，出現在頁面上的訊息，例如“Ticket description 是必填欄位” 的“Ticket description “是怎麼來的？因為在程式碼裡，我以搜尋的方式，也沒有搜尋到，可請助教給提示嗎？
ValidateJs程式碼的部分是有參考[這裡](http://validatejs.org/examples.html)而改寫，但可能關年還不夠清楚，導致改的有點亂，抱歉啊！
再請助教解惑了～感謝～ 
> 助教回覆：
> 同學會跳錯是因為 HTML 的 90 行 name="套票描述" 沒有刪掉， 一個標籤有兩個 name 屬性會判斷錯誤。 刪掉就正常了。
>
> Ticket description 是同學 textarea 欄位的 name 的 ticketDescription 來的。 因為我把它改成 abc 也會回傳給我 「Abc 是必填欄位」。 似乎是會自動幫你轉大寫 & 斷行。
>

---
<font color="#e5b3cc">17. **Fred Chang**　🍒　</font>
問題1、2已理解，但第3個問題其實我在JS的第90行有把class換成deleteAllBtn ，且即使我改成原始HTML結構的discardAllBtn點選也還是不會有反應，請問助教能再次協助解答嗎? 謝謝
> 助教回覆：
> 渲染出來的 DOM 沒辦法使用 addEventListener 喔。 可以監聽他的外層去選到對應的節點， 但無法把它當作一個按鈕掛監聽。 
> 上次發問的 「為什麼第53行宣告shoppingCart又是可以抓到的呢?」 是因為 shoppingCart 本身是寫在 HTML 上的結構， 當然要直接監聽他是沒有問題的。 
> 這邊的解決辦法有兩種， 
> 1. 使用像單一刪除的監聽方法去選到那個刪除全部的節點。
> 2. 直接拆開來把它寫在 HTML 上不要用渲染的， 這樣就可以直接抓到按鈕節點監聽。 
> 
> 同學再試試看哩！ 有問題也可以繼續發問喔！ （ 售後服務 ）