# [Vue.js] 進階教學筆記 ###### tags: `Vue.js` ### 1. 關閉鈕aria-label: 一個 HTML attribute,用來告訴讀屏軟件某個元素是什麼。例如一個關閉按鈕「×」,視覺上看來都能理解,但是讀屏軟件並不能正確讀出,這時就可以用 aria-label 告訴它: `<button aria-label="關閉">&times;</button>` 2. 關閉按鈕結合aria-hidden ``` <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">&times;</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做連結 ![](https://i.imgur.com/5hNMpzP.png) ``` //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> ``` ![](https://i.imgur.com/J99Gt15.png) ``` 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/) ![](https://i.imgur.com/FQ48XU7.png) v-if只會渲染滿足條件的而隱藏另一條件, ![](https://i.imgur.com/eCZTLqh.png) v-show會渲染滿足條件的,然後顯示關閉另一條件。 ![](https://i.imgur.com/6gZFdgM.png) ### 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}` } } ``` ![](https://i.imgur.com/X9dGUuh.png) ### 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; } ```