---
# System prepended metadata

title: 7/5 線上 Slack 助教
tags: [Vue 直播班 - 2021 夏季班]

---

---
tags: Vue 直播班 - 2021 夏季班
---

# 7/5 線上 Slack 助教


## 今日助教輪班時間

hsin-yu：7/5 (一) 
回覆時間：下午 1:00 -下午 4:00

## 發問規範

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

## 注意

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

## 問題

1. Tori：
助教你好，這是我的
 [Github](https://github.com/aer456987/natural/blob/main/src/components/modal/DashboarCouponModal.vue) 
 [github pages](https://aer456987.github.io/natural/dist/#/login) 
我想在後台的 商品modal 和 優惠券modal 中使用 VeeValidate 套件進行驗證，助教可以看 DashboarOrderModal.vue 那份的程式碼(33行開始)。
刷新頁面後，點擊新增 modal，套件可以正常驗證，接著點開修改 modal 也可以正常驗證。
**但如果這時候再點擊一次新增 modal 就會出現跳錯誤(附圖)，上一筆資料在畫面上不會被清除(但用vue看會發現資料確實有被清除)**
想問助教這種狀況是哪種問題導致的？
> 助教回覆：
> 這裏因使用 VeeValidate 套件驗證 from 裡面的值不能沒有屬性，不然會無法辨識
以優惠券頁面為例，原本在 DashboardCoupon.vue 打開 modal 時會將 
updataCouponData 重新設定（[這段](https://github.com/aer456987/natural/blob/main/src/views/admin/DashboardCoupon.vue#L162-L165)）
需將所有的屬性都補上才能正確執行驗證
可以在 DashboarCouponModal.vue 打開 modal 的部分將 tempCouponData 設定為
```{
    due_date: Math.floor(Date.now() / 1000),
    is_enabled: 0,
    code: ‘’,
    id: ‘’,
    num: 0,
    percent: 0,
    title: ‘’,
};
```
>（這部分也可以參考 [Vue3 直播班 vee-validate 4 問題紀錄](https://hackmd.io/fKY90dVxQtm4qJKfBchj3Q)，同學的問題和第二個問題類似）
>
>這樣修改後不會跳出錯誤，不過會出現：打開 modal 因改變 tempCouponData 中的值而觸發表單驗證的情況，
>目前測試可以在設定 tempCouponData 值之前使用 veevalidate 的內建函式 resetForm() 將表單在不觸發驗證的情況下清空值，打開 modal 新增優惠券時就不會在一開始就觸發驗證






---

2. Stacey Huang:
hsin yu 助教你好
關於 Ray 助教提供的第7周 [作業範例](https://github.com/hexschool/live-vue3-dashboard) ,有些問題想要提問。不好意思,問題有點多。
(1)在couponModal.vue中的line84行,Ray助教有註解將時間格式改為 YYYY-MM-DD,想請問這個時間格式是由後端所決定嗎? 一開始沒有注意到要用YYYY-MM-DD,改用其他方式將timestamp轉 YYYY/MM/DD 結果出現錯誤。

>助教回覆：
>這裏因 input type="date" 的 value 主要是接受 yyyy-mm-dd 的日期格式（根據 ISO 8601 國際標準化組織的日期和時間表示方法）
可以參考[<input type=“date”> - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/date)
其中 Value 的部分有提到:
>```
>The displayed date format will differ from the actual value — the displayed date is formatted *based on the locale of the user’s browser*, but the parsed value is always formatted yyyy-mm-dd.
>```

(2)Article.vue利用props將資料傳到 ArticleModal, tempArticle已經包含了tag及isPublic(line124~128),所以不是很清楚為什麼在ArticleModal中,在line 197中, 將this.article淺拷貝並賦於到this. tempArticle,為甚麼還需要tag及isPublic(line 198及 line 199)呢?
>助教回覆：
>這個問題最主要是發生在新增後再去編輯
當使用者如果新增時沒有新增標籤就儲存的話，此時陣列會是空的，而這時候再點一次沒有儲存陣列的資料編輯，這時候跟後端請求的資料就不會帶有 tag 屬性，因此這邊在 Article.vue 淺拷貝下去 this.tempArticle = { ...item }; 如果沒有針對 watch 做一些處理的話是會出現錯誤的

(3)在Article.vue中為什麼在line91 和line111行中,為甚麼會特別使用catch呢?
已經知道當請求失敗時,axios會使用catch來處理,但因為在其他請求中,大多沒有用到catch,幾乎都使用if(res.data.success)與else來做判斷,因此想請問一下。
以上問題,再麻煩助教了,謝謝!
>會建議串接 API 都要接上 catch，為了接收錯誤訊息，而這邊主要是因為每一個後端開 API 方式不同，所以這隻 API 主要是用 if...else 去錯判斷，但是如果出現一些特別的錯誤的時候，例如 5xx 就不會進入 then，因為是屬於 catch
可以測試以下例子，例如：
>```
>const api = >${process.env.VUE_APP_API}/api/${process.env.VUE_APP_PATH}/admin/article/${id};
>```
>改成
>```
>const api = >${process.env.VUE_APP_API}123/api/${process.env.VUE_APP_PATH}/admin/>article/${id};
>```
>這時候如果沒有 catch 是不會出現錯誤訊息的~ 

---

3. Jordan_Tseng :
老師、助教、同學好，**
這是我的，我想問幾個問題：
(1) 在 [新建職位表單](https://github.com/Jordan-TTC-Design/vue-2021-finalwork/blob/master/src/views/front/AddJob.vue) 中遇到一個問題是，兩個單選選項一樣，就會打架衝突，如果選其他事可以運作。
>這部分想確認同學指的「兩個單選選項一樣會衝突」的具體情況是什麼呢～（是指單選的選項會需要重複，例如：選項一、選項一、選項二 嗎～）
>
>更新：這裏可以調整 input 的 name 屬性，若有五個單選 (radio) 都屬於「工作經驗」選項，這五個選項的 name 必須為相同值，「學歷要求」的五個選項的 name 值也需相同
>可以參考 [<input type=“radio”> - HTML（超文本标记语言） | MDN](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/Input/radio)，其中有提到
>```
>一個單選按鈕組由具有相同 name 屬性的單選按鈕組成。一個單選按鈕組被建立，選擇那組的任何單選按鈕將自動取消同組當前選擇的任何按鈕
>```
(2)想問在後台產品頁，因為我需要很多產品，我是想取得全部產品列表，全部產品會回傳物件，我找了一個物件轉陣列方式，目前看是可以運作，不知道對不對：this.products = Object.keys(res.data.products).map((_) => res.data.products[_]);
>從 vue 開發者工具查看 products 資料有正確呈現每個產品物件，轉換型別上沒問題哩

(3)我想刪除 [訂單](https://github.com/Jordan-TTC-Design/vue-2021-finalwork/blob/master/src/views/admin/DashBoardOrdersList.vue) 、產品時，當下陣列會再次塞入回傳的東西，我覺得是我在分類時出問題可能是.forEach，但是像我訂單陣列getOrder中也有塞入歸零，但沒效果，不知道怎麼做比較好？
this.addCompanyOrders = [];this.addjobOrders = [];
助教如果要測刪除，可以先從訂單列表按創建，訂單目前設固定的
>這部分也需要請同學多描述一點，讓我們暸解實際上要的需求是什麼，若是以功能來看是正常的
>更新：
>因刪除產品之後會執行取得全部產品，然後透過 map 轉換成新的陣列，接下來會執行 classifyProduct methods 篩選出產品分類，而這邊並不是重新賦予的方式，而是採用 push，因此篩選完之後就又新增了，因此可以改為每次跑這個 forEach 之前都應該要將相關 companiesList 與 jobsList 清空一次，這樣才不會又發生同樣狀況


(4)最後想問說，如果兩個類似modal，像是後台訂單、產品頁面我有企業和職位，我用v-if讓他暫時不存在，因為modal中有些資料還沒生成，避免出現錯誤。但是就變成要多按一次，不知道助教有沒有比較好建議？
> 這裏提供大概方向讓同學思考調整看看：
因同學有提到「如果兩個類似modal，像是後台訂單、產品頁面我有企業和職位」，所以會建議 props 的時候可以傳入一個判斷式到 Modal 在裡面辨別哪些是後台訂單、產品頁面專用的 Modal，而不是直接補在外層 v-if，這樣會出現目前的問題（必須點兩次），因為元件要重新經歷渲染，正確應一開始就一先讓元件渲染，接下來透過傳入的 props 來去 v-if 切換元件內部該顯示的
例如：我們可以透過 props 傳入 status : true or false，然後 Modal 裡面就可以去切換要顯示的 HTML


---
4. Iven :
助教好：
Q1 : 這是我的程式碼，有點不太了解ToastMessages的部分，是怎麼觸發他跳出訊息的，因為我實作時，一開始就算emitter.on有監聽到事件觸發，但是也沒有跳出訊息，後來對照範例程式碼，在toast加上 class= toast show 才順利跳出提示訊息，所以有點不懂，toast是怎麼顯示出來的。
>助教回覆：
>因範例的部分是預設 toast 是顯示的狀態（因此會在 class 加上 show，.show 是 bootstrap 的樣式，
>```
>.toast:not(.showing):not(.show) {
>  opacity: 0;
>}
>```
>如果沒有同時出現 .toast 和 .show，透明度就會是 0）
>顯示 toast 部分改為：若 messages 有內容就會顯示 toast 的 html 結構 [參考這裡](https://github.com/hexschool/live-vue3-dashboard/blob/main/src/components/ToastMessages.vue#L7)（使用 v-for 渲染 messages 的部分，當 messages 是空的就不會出現了）
>Messages 的值也是另外寫方法：
在 push-message 事件發生時將提示訊息推到 ToastMessages.vue 的 messages 中
（ [參考 PushMessageStatus.js](https://github.com/hexschool/live-vue3-dashboard/blob/main/src/methods/pushMessageState.js)


Q2 : 為什麼PushMessageStatus裡面的export default function不用加上名稱？
>助教回覆：
>可以參考這裡 [export - JavaScript | MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Statements/export#%E4%BD%BF%E7%94%A8%E8%AA%AA%E6%98%8E) export 有兩種使用方式，一種是需要命名的，另一種就是 export default … ，若使用 export default 的方式可以不用名稱～


Q3 :第11行的三元運算子 const message = typeof res.data.message === 'string' ? [res.data.message] : res.data.message
是說 如果回傳的 res.data.message 型別是字串的話 就包成物件，如果不是字串的話，就保持原本的型別嗎？ 我覺得我解釋得有點怪怪的，想請問助教有更好理解的解釋嗎？
>助教回覆：
>同學的解釋是沒錯的，這裏因回傳的 response.data.message 會有字串或陣列的格式，因此透過判斷式將格式一律統一為陣列格式哩


---

5. Tori:
[Github](https://github.com/aer456987/natural/blob/main/src/components/ProductCard.vue) 
 [github pages](http://localhost:8080/natural/dist/#/products) 
(問題一) 我正在製作加入最愛的功能，產品 id 可以在存入 localStorage 時同時讀取 localStorage 的資料(第 139 行)。
但如果這時重新刷新頁面時就會報錯(附圖)，第 77 行的 this.$refs.favorit.getFavorits() 拿掉就不會報錯。
但是這樣會導致每次刷新頁面時，myFavorits 的資料同時變成空陣列，請問助教這個問題我該怎麼處理？
>如果是在第 77 行 使用 ref 選取 DOM 元素，因無法確定載入 data() 時整個 DOM 是否已載入完成，當找不到 this.$refs.favorit 就會出錯
可以直接將 this.myFavorits 設定
JSON.parse(localStorage.getItem(‘favoritData’)) || [] 取得 localStorage 的資料

(問題二) 關於助教上個問題的解答：目前測試可以在設定 tempCouponData 值之前使用 veevalidate 的內建函式 resetForm() 將表單在不觸發驗證的情況下清空值，打開 modal 新增優惠券時就不會在一開始就觸發驗證
我查過了官方文件，但還是不太懂resetForm() 使用方法，再請助教解惑，謝謝。
>這邊可以參考助教範例中的寫法，用 refs 選取 form 執行 resetForm()
[範例](https://github.com/hexschool/live-vue3-dashboard/blob/17da34a50d11826b7c4689fa6c2f2cf9d7f55cb2/src/views/UserCart.vue#L372)


---

6. moitw
助教好，這是我的  [code](https://github.com/tsuifei/vue-galerie/blob/main/src/components/AdminCouponModal.vue)   和  [page](https://tsuifei.github.io/vue-galerie/dist/#/) 
在寫 coupon 的 modal 時，一直無法觸發父層的方法 updateCoupon 出現的錯誤是：Property “updateCoupon” was accessed during render but is not defined on instance
有在父層子層寫了emit 與橋樑，但開啟視窗修改後點確定沒反應，有測試點擊其他方法沒問題，但是就是點擊觸發父層一直沒反應，想麻煩助教幫忙找盲點，應該是emit 的問題自己卻查不出來，另外，在 AdminCouponModal 李的日期也一直無法正確顯示，找不出是哪裡的問題….先謝謝助教～
>Coupons.vue [這邊](https://github.com/tsuifei/vue-galerie/blob/main/src/views/admin/Coupons.vue#L118 )定義的 updateCoupon 函式有多一個字 
以及137 行[這裡](https://github.com/tsuifei/vue-galerie/blob/main/src/views/admin/Coupons.vue#L137)應該是 getCoupons
調整後應該就可以正確執行，可以調整看看～

>時間的部分可以參考上方第 2 題同學的提問（第 1 小題），因 input type=“date” 的 value 主要是接受 yyyy-mm-dd 的日期格式，這邊看 AdminCouponModal.vue [這裡](https://github.com/tsuifei/vue-galerie/blob/main/src/components/AdminCouponModal.vue#L133-L135) 有將 this.temp_due_date 轉為 yyyy-mm-dd 的日期格式，因此 modal 中 input type=“date” 應該綁定 temp_due_date，才會正確顯示日期（不需轉為 number 型別）

---

7. 蔡皓全
助教好:  
1.我想請問要客製化bootstrap中的button樣式的話，我看了一下文件很像是要先定義一個class名稱，然後在裡面寫@include button-variant(代入的參數)，但我看不懂參數的位置分別代表怎樣的樣式，假設用`$primary`的背景色 文字是`$white`，hover後變`$success` 背景色文字是`$success`這樣該怎麼寫   
> 因 bootstrap 的 hover 顏色都是根據背景色調深或調淺一定比例
如果是想從 A 背景色的 button，hover 時改為完全不同的 B 背景色，可能需要另外客製化 btn 的樣式，不使用 btn-primary 的 class，客製化 .btn-custom，hover 的樣式就可以另外設定，例如：
>```
>.btn-custom { 
>   background-color: $primary;
>   &:hover {
>      background-color: $success;
>   }
>}
>```

2.我想問關於使用vue-typed-js 我照著這份 [文件](https://github.com/Orlandster/vue-typed-js)  使用，但加上Index.vue檔中的第7和第9行就會失敗 附上 [github](https://github.com/DavidTsai-whole/vuecli3)   謝謝
>這裡查看 vue-typed-js GitHub 是支援 vue2 的，目前沒有找到是否有支援 vue3 的說明，同學可以先看看是否有支援 Vue3 的替代的套件，或其他方式達成 typing 的動畫效果哩
>
>更新：這裏提供葉子助教的[文章](https://tzuhui.github.io/2019/11/13/CSS/css-typewriter/)，也可以參考這裡做法呈現打字機效果唷

---
8. Tori 
助教你好，一樣是 VeeValidate 的問題
 [Github](https://github.com/aer456987/natural/blob/main/src/views/admin/DashboardCoupon.vue) 
 [github pages](https://aer456987.github.io/natural/dist/#/admin/coupon) 
依助教的解答加入了 resetForm() ( 第 163 行 )，初次點開新增 modal 後會出現 VeeValidate 的驗證訊息，關掉再點一次，驗證訊息就會消失，不太確定自己指令寫的位置是不是對的，再請助教幫忙看看。
>這裡原本提供的寫法是把這段 [這段](https://github.com/aer456987/natural/blob/main/src/views/admin/DashboardCoupon.vue#L163-L170) 放在 DashboarCouponModal.vue 的 openCouponModal() 函式中，同學目前的寫法也是可以的，但需注意初次打開新增 modal 時，因 DashboarCouponModal.vue 這邊 tempCouponData
原本的值是空物件 {}，當資料賦予 tempCouponData 值有變動也會觸發驗證，因此可以在[這邊](https://github.com/aer456987/natural/blob/main/src/components/modal/DashboarCouponModal.vue#L189)也設定每個屬性的初始值，初次打開就不會再觸發驗證了
---

9. Jordan_Tseng
助教好，我原本那篇留言有在留影片。這是我的 [頁面](https://jordan-ttc-design.github.io/vue-2021-finalwork/dist/#/products-list) 、。另外想問關於position-sticky的問題，我明明有設定但是他就是出不來，滿奇怪。header時好時壞。我查好像是說外層不能有overflow?外層也沒有這個設定
>這邊用同學提供的頁面操作，滾動頁面時上方導覽列都有固定在視窗上方，效果有正確呈現（不確定同學是否已調整過）
另外同學提供影片的問題有回覆在原本第 3 題問答中，可以調整看看～

>更新：
>因 position: sticky 是讓元素相對於他的外層固定，例如：header 是相對外層 `#app`，因此會固定在 `#app` 最上方
右側職位顯示框 jobSelectBox 和外層 .col-md-6 高度是相同的，因此會沒有固定的效果，需要將 jobSelectBox 移到外層，讓他相對於 `#app` 定位，滾動視窗才會有固定的效果


---
(這邊只能由助教編輯，問題請到 thread 上詢問)