# [Vue.js] 進階教學筆記
###### tags: `Vue.js`
### 1. 關閉鈕aria-label:
一個 HTML attribute,用來告訴讀屏軟件某個元素是什麼。例如一個關閉按鈕「×」,視覺上看來都能理解,但是讀屏軟件並不能正確讀出,這時就可以用 aria-label 告訴它:
`<button aria-label="關閉">×</button>`
2. 關閉按鈕結合aria-hidden
```
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
```
3. 刪除鍵的js語法
```
removeTodo: function(key){
this.todos.splice(key , 1)}
//串連html裡key的陣列值,再使用splice刪除陣列裡的幾筆資料
```
### 4. checkbox的連結語法:
下面有兩個元素,一個是checkbox,另一個是label,不管點哪一者都會得到一樣的結果,其原理是用 label for 對應checkbox的id,這樣兩者就會產生連動效果(html 的概念);
input有個id,label有個for,兩者是透過id與for做連結

```
//html code
<input type="checkbox" id="a1">
<label for="a1"></label>
```
### 5. 要綁定style的宣告,可使用class呼叫
:class="{'觸發completed': 條件item.completed}"
```
<li><a class="active" href="#">選項 1</a></li>
```
選項 1 不總是被選定的,而是依賴一個參數「isActive」決定-若 isActive 值為 true 才會被選定
```
<li><a :class="{ active: isActive }" href="#">顯示</a></li>
```
```
data: {isActive: true}
```
### 6. String.trim() 去除字串前後的空白
### 7. 利用時間製造獨一無二的亂數ID
Math.floor(Date.now()) 取得現在時間
* Date.now() 可以取得現在 UTC timestamp 的 milliseconds (毫秒, 即千分之一秒)。只要將這個數值除 1000, 即可得到
* Math.floor() 函式會回傳無條件捨去後的最大整數
### 8. 迴圈forEach用法
forEach函式執行每個陣列內的物件或值
```
this.todos.forEach(function(item){
if(item>2){
console.log(item)
}}
//在this.todos陣列裡,使用item的資料做迴圈判斷
```
### 9. 模板資料
Data使用<-span>型態
容易導致XSS攻擊,允許惡意程式將程式碼注入到網頁上
### 10. 動態切換className及style的方式
#### 一.基本用法
在style放入動態效果A跟B
在botton放上@click啟動,寫的方式是A=!A(點擊後會開啟)
在checkbox放上v-model啟動,寫入B的style名稱
在顯示位置上放入:class={'效果':條件}
#### 二.使用data統一管理
稱為:物件寫法
在data裡放上物件{A效果,B效果}
在顯示位置僅放入物件名稱就可以
在botton放上@click="物件名稱.A效果= !物件名稱.A效果"
#### 三.陣列方式
適用在不確定className長度,非用布林值,而是用陣列的方式加入,所有的效果都寫在html裡。
在data新增一個空陣列Classarry
在顯示位置放上陣列名稱Classarry
在checkbox1放上@click="陣列名稱" value="A效果"
在checkbox2放上@click="陣列名稱" value="A效果"
### 迴圈區別
[參考資料](https://www.ucamc.com/e-learning/javascript/261-javascript-reduce%E3%80%81foreach%E3%80%81filter%E3%80%81map)
* forEach:遍歷每個元素。
* map:遍歷每個元素,回傳的值會替代原本陣列內的值。
* filter:遍歷每個元素,回傳 true 時,目前的值會保留在陣列內,這會回傳一個新陣列,而不是修改原本的陣列。
* reduce:遍歷每個元素,依序組合、加總,然後丟給下個元素,最終會回傳一個結果。
### 11. 輸入的人名相同後便顯示相關資料,by迴圈filter
* Filter簡介
這個按照字面上的意思來說就是過濾器,filter 不會修改值,但他會幫你決定要不要將這個值留在陣列裡面,要注意的是 filter 會回傳一個新的陣列,而不是修改原本的陣列。
* 功用:當輸入的人名對應到陣列人名時,便可顯示此人的詳細資料
* 方式:將原陣列帶入filter迴圈裡,載入match公式,
為了將陣列做過濾,因而新增一個新陣列filterArray,將此陣列指到原陣列做迴圈(結論:陣列迴圈需要再創一個新陣列)。
使用filter公式做迴圈:this.arrayData.filter(function(item)){內容}
導入match公式 : 陣列.match(輸入內容v-model串連的變數)
寫入的人名就對應match到陣列裡的人名就會顯示詳細資料
```
<input type="text" class="form-control" v-model="filterText" @keyup.enter="filterData">
<ul>
<li v-for="(item, key) in filterArray" :key="item.age">
{{ key }} - {{ item.name }} {{ item.age }} 歲 <input type="text" >
</li>
</ul>
```

```
filterData: function () {
var vm = this; //做for迴圈,this會被替換掉,此處宣告this就可以重新使用
vm.filterArray = vm.arrayData.filter(function (item) { //將新增的filterArray陣列定義成==原本的陣列(arrayData),套用filter迴圈公式代item值
return item.name.match(vm.filterText); // 寫入的人名就對應match到陣列人名就顯示 //match公式 : 陣列.match(輸入的內容)
});
},
```
> 在filter公式裡只要return是true狀態便會將item物件傳到vm.filterArray,直接顯示出來
### 12. Vue.set更改陣列內容
在vue要將新資料寫入陣列時,可使用 Vue.set(陣列array, 第幾筆index, value) 來達到修改資料目的
```
Vue.set(this.arrayData, 0, {
name: '阿強',
age: 99
})
```
### 13. 迴圈使用template不輸出
```
<ul>
<template v-for="(item,index) in foodsArray" :key="item.id">
<li><span>{{item.name}}</span></li>
<li><span>{{item.price}}</span></li>
</template>
</ul>
```
可將輸出群組化,且template不會被輸出
在html當作Dom元素,使用<template></template>載入v函式,並且不會出現在頁面中。
### 14. :key使用方式
v-for中的key
使用v-for更新已渲染的元素列表時,預設用就地複用策略;列表資料修改的時候,他會根據key值去判斷某個值是否修改,如果修改,則重新渲染這一項,否則複用之前的元素;注意上面key值不要用物件或是陣列作為key,用string或number作為key
```
<ul>
<li v-for="(item) in arrayData" :key="item.name">
{{ item.name }} {{ item.age }} 歲 <input type="text">
</li>
</ul>
```
:key
Vue 在更新 DOM 時是異步執行的,若不設定 key 值,不會重新渲染元素,只會部份更新。所以可給每個元素加上:key ,key值必須綁定一個唯一值,也就是確保每個元素的唯一性。
#### 說明 Vue 切換狀態可能遇到的問題
功能切換input項目內的狀態,先輸入username,後跳轉至email輸入,因兩者語法相似,需要個別增加不同key值程式(key="1"及"2")才能進行跳轉,否則程式會判定兩者語法一樣而僅做工一則
```
<template v-if="loginType === 'username'">
<label>Username</label>
<input class="form-control" placeholder="Enter your username" :key="1">
</template>
<template v-else>
<label>Email</label>
<input class="form-control" placeholder="Enter your email address" :key="2">
</template>
<button class="btn btn-outline-primary mt-3" @click="toggleLoginType">切換狀態</button>
<hr>
```
### 15. v-if及v-show的差異
[參考資料](https://cythilya.github.io/2017/04/22/vue-conditional-rendering/)

v-if只會渲染滿足條件的而隱藏另一條件,

v-show會渲染滿足條件的,然後顯示關閉另一條件。

### 16.v-for與v-if 優先權的比較
v-for的優先權高於v-if,因此當兩者皆出現在同一個元素上時,v-if會隨著v-for重覆執行數次。
### 17. watch當變數產生變化,便會執行特定function
當特定的變數產生變化,會執行特定的function。
範例,當trigger點擊後三秒將trigger布林值修改成false
```
<p>使用 trigger 來觸發旋轉 box、並在三秒後改變回來</p>
<div class="box" :class="{'rotate': trigger }"></div>
<hr>
<button class="btn btn-outline-primary" @click="trigger = true">Counter</button>
```
```
watch:{
trigger:function(){
var vm = this;
setTimeout(() => {
vm.trigger = false
}, 3000);
}
},
```
*補充:watch非放置在computed內,而是平行階層
### 18. mounted時間格式
Computed 來呈現時間格式:
這邊我們會用到 mounted,它同樣是 vue 提供的 api,意義是當我們畫面運行完畢之後執行某段程式碼。
* 補充:mounted,而是平行階層
```
// 1. mounted 等待運算結束後在掛載上後續要做的事情
// 2. 先把 newDate 放到第二個 p 標籤裡面看看會是呈現什麼
<p>使用 Computed 來呈現時間格式。</p>
<p>{{ newDate }}</p>
mounted: function() {
this.newDate = Math.floor(Date.now() / 1000);
},
```
畫面會出現一串數字是 timeStamp 可以透過 JS 來轉換成我們人所看得懂的日期格式,這裏我們用 computed 來改成我們日常看得懂的格式。
```
computed: {
formatTime: function() {
console.log(this.newDate
// 用 new Date 把值轉回原本的時間格式,newDate 時間長度可能不足所以 * 1000補回原本長度
let dates = new Date(this.newDate * 1000);
// 以下都是取出時間格式的方法
let year = dates.getFullYear();
let month = dates.getMonth() + 1;
let date = dates.getDate();
let hours = dates.getHours();
let minutes = dates.getMinutes();
let seconds = dates.getSeconds();
// 最後將我們時間的格式拼成我們所要的
return `${year}/${month}/${date} ${hours}:${minutes}:${seconds}`
}
}
```

### 19. forEach迴圈
目的:在原陣列裡做if判斷式,並顯示不同的結果
```
const items = ['item1', 'item2', 'item3'];
const copy = [];
items.forEach(function(item){
copy.push(item)
});
```
搭配computed函數宣告使用,先宣告一組空陣列copy,此時套用forEach公式並把篩選後的結果push至新陣列copy裡,顯示在畫面上。
> function裡的item是變數,可任意更改,但盡量還是統一使用
```
if(this.visibility == 'active'){ //重點部分,剩兩個部分用判斷式(completed的布林值)來區分
var newTodos=[]; //新陣列
this.todos.forEach(function(item){ //forEach函式執行每個陣列內的物件或值,取用原先todos
if(!item.completed){
newTodos.push(item); //符合條件的輸入至新的陣列newTodos裡
}
})
return newTodos;
}
```