# Vue3 學習筆記 ## JavaScript ES6 複習 ### 變數(var, let, const) ###### 使用 var: 這邊 if 判斷式中的 arr 變成了全域變數。 :thought_balloon: 何時用 var,自ES6版本開始後,我們將會只會用到 let 和 const 。 ```javascript= var arr = [a, b, c]; if(ture){ var arr=[]; } console.log(arr); // => [] ``` ###### 使用 let: 改用 let 將會把影響範圍限縮於判斷式內(區域變數),不再影響 arr 。 :thought_balloon: let 的範圍是由{}去界定的。 ```javascript= var arr = [a, b, c]; if(ture){ㄍ let arr=[]; } console.log(arr); // => [a, b, c] ``` ###### 使用 const: 使用 const 有不能夠被修改的特性。 :thought_balloon: 取 DOM 元素時,使用 const ,而非 let 因為我們並不會去修改 DOM 元素。 ```htmlmixed= <a id="link"></a> <script> const dom = document.getElementById('link'); </script> ``` 比較嚴謹的狀況下,使用 const 來宣告物件以及矩陣。 :thought_balloon: 在 javaScript 中使用 const ,只有 Obj (物件)以及 Array(矩陣),可以增加其內容,但前提是不可以修改其原本的類型。 ```javascript= const a = { name: "mike"}; a["age"] = 12; console.log(a); // => { name: "mike", age: 12} const b = []; b = 123; console.log(a); // => Uncaught TypeError: Assignment to constant varible at ... ``` ###### Vue3基本文法型態: ```javascript= // Composition API plugin const { **要叫出的工具** } = Vue; // RootComponent const App = { setup() { // Options // Return variable return { **要回傳的值** }; } }; // Create Vue application Vue.createApp(App).mount(" **洞元素** "); ``` ### 解構賦值(Destructuring assignment) 告別 **Varible.Key**,擁抱解構方法,不需再一個個改,也和冗長複雜的結構說再見。 ###### 方法一(嵌入新參數): ```javascript= const data = { name: "mike", age: "12", address: "Taiwan" }; const { name, age, address } = data; // console.log(data.name, data.age, data.address); console.log(name, age, address); // => mike 12 Taiwan ``` ###### 方法二(嵌入新物件): ```javascript= const data = { name: "mike", age: "12", address: "Taiwan" }; const user = { data, sextual: male } ``` ### 箭頭函式運算式(Arrow Function) 使用箭頭函式代替原本的function關鍵字。 ###### 箭頭函示寫法: ```javascript= (**值**) => { // Options }; ``` ###### 兩者的不同(this、e.target): :thought_balloon: function關鍵字與箭頭函式**並不完全相同**,前者可以使用this,而後者並無this,只會指向其上一層(Windows)。 ```htmlmixed= <a id="link1" href="javascript:;">link1</a> <a id="link2" href="javascript:;">link2</a> <script> // 使用this document.getElementById("link1").addEventListener("click",function() { console.log(this); // => <a id="link2" href="javascript:;">link1</a> }); // 使用e.target document.getElementById("link2").addEventListener("click", (e)=>{ console.log(e); // => <a id="link2" href="javascript:;">link2</a> }) </script> ``` ###### 宣告函式: 利用變數方式,來指定一個function的使用。 ```javascript= const Add = (a,b) => { retrun a+b; } console.log(Add(1,3)); // => 4 ``` :thought_balloon: 如果return只有**一行**的話,可以省略掉大括號(如下) ```javascript= const Add = (a,b) => a+b; ``` ### 預設值(Function Default) 範例將陣列中的數字型態轉為字串。 :thought_balloon: 使用預設值可以避免掉一些初階的函式錯誤。 ```javascript= // 原語法 const ArrToStr = (arr) => { // 如arr為undefind,則設為空陣列 if(!arr) arr = []; const mapStr = arr.map((item) => { return item + ""; }); return mapStr; } // 使用預設值語法 const ArrToStr = (arr = []) => { const mapStr = arr.map((item) => item + ""); return mapStr; } console.log(ArrToStr()) // => [] console.log(ArrToStr([1, 2, 3])) // => ["1", "2", "3"] ``` ### 字串模板(String template) 利用反斜線(Literal)建立字串模板,並利將參數放數錢字號大括號之中。 :thought_balloon: 字串模板支援換行的功能,用起來更加方便。 ```javascript= const add = (name, age) => { // return "hi我叫"name+",我今年"+age+"歲" return `hi我叫${name},我今年${age}歲` } console.log(add("mike", 12)); // =>hi我叫mike,我今年12歲 ``` ### 模組(Module) :thought_balloon: Module 中,有 export default(**預設丟出**)與export (**選擇性丟出**),而一個 Module **只能有一個 export default**,另外 export 出去的類型只能夠是 **const**。 ```javascript= const Add = (a, b) =>{ return a+b; } // 透過解構取出 export const name = "mike"; export const age = 12; export const Remove = (a, b) => a-b; // 直接取出 export default Add; ``` :thought_balloon: 直接使用import的方式拉入,不用使用src拉入資源在寫入。 ```htmlmixed= <script type="module"> import Add, { name, age, Remove } from "URL" </script> ``` ## Vue 基礎入門 ### 起手式(Create App) ###### 步驟: 1. 先將 Vue 掛載入檔案中。 2. 在 Body 中最外圍建構一 div 元素(Vue的控制範圍)。 3. 建立一 const 物件 4. 創造 Vue 應用程式本身,並渲染至指定的 ID。 ###### 基本結構: ```htmlmixed= <!-- 渲染目標 --> <div id="app"></div> <!-- 掛載 Vue --> <script src="./js/vue.js"></script> <script> // 要從 Vue 解構的方法 const { 方法 } = Vue; // Vue操作內容 const App = { setUp() { return { 參數 }; } }; //創建 Vue 並渲染至目標 Vue.createApp(App).mount("#app"); </script> ``` ### ref 透過 ref 包裝,才能做到資料的綁定以及修改。 :thought_balloon: 可以接受各型別的參數定義。 ###### 解構與綁定: ```javascript= // 解構 ref const { ref } = Vue; const App = { setUp() { // const text = Vue.ref("Mike"); const text = ref("Mike"); return { text }; } }; Vue.createApp(App).mount("#app"); ``` ###### 資料修改: :thought_balloon: 兩個大括號為 Vue 的**字串模板**。 ```htmlmixed= <div id="app"> <h1>{{text}}</h1> </div> ``` :thought_balloon: 再 ref 包裝過後,會回傳一個物件,而如要修改資料的值則要透過物件中的 **value**。 ```javascript= const { ref } = Vue; const App = { setUp() { const text = ref("Mike"); setTimeout(()=>{ text.value = "John"; },1000); return { text }; } }; Vue.createApp(App).mount("#app"); ``` ### reactive :thought_balloon: 只能接受陣列或物件兩種類型的值。 ```htmlmixed= <div id="app"> <h1>{{message.text}}</h1> </div> ``` ```javascript= const { reactive } = Vue; const App = { setUp() { const message = reactive({ text: "Hello Vue" }); return { message }; } }; Vue.createApp(App).mount("#app"); ``` ### 選擇 ref 還是 reactive 大多數情況下兩者可以交互使用,主要取決個人喜好或團隊習慣,根據具體情況去決定要使用那個好。 ###### 兩者差異: * ref:可以定義**任何型別的值**,但不會對物件或陣列內的屬性變動做監聽。 * reactive:只能定義物件或是陣列,可以**深層監聽**,以及**訪問資料不需要使用 .value**。 ### 資料雙向綁定(Two way bind) 利用模板語法 **v-model** 對 input 以及資料做雙向綁定。 ###### 範例一(輸入列綁定標題) ```htmlmixed= <div id="app"> <h1>{{text}}</h1> <input type="text" v-model="text"> </br> <h1>{{message.text}}</h1> <input type="text" v-model="message.text"> </div> ``` ```javascript= const { ref, reactive } = Vue; const App = { setup(){ const text = ref("Mike"); const message = reactive({ text: "Hello Vue" }) return { text, message }; } }; vue.createApp(App).mount("#app"); ``` ### 事件綁定(On event) 使用 **v-on** 將return出的函式與事件綁定。 :thought_balloon: v-on:click 可簡寫為 @click。 ###### 範例一(按鍵加減) ```htmlmixed= <div id="app"> <h1>{{num}}</h1> <button v-on:click=AddFn>Add</button> <button v-on:click=MinusFn>Minus</button> </div> ``` ```javascript= const { ref } = Vue; const App = { setUp(){ const num = ref(0); const AddFn = () => num.value++; const MinusFn = () => num.value--; }; return { num, AddFn, MinusFn }; } Vue.createApp(App).mount("#app"); ``` ### 唯讀 (readonly) 避免修改到參數,當修改到readonly定義後的參數,Vue 會返回失敗。 ```htmlmixed= <div id="app"> <button @click="Change">Add</button> <button @click="ChangeCopy">CopyAdd</button> </div> ``` ```javascript= const { ref, readonly } = Vue; const App = { setup() { const Num = ref(0); const CopyNum = readonly(Num); const Change = () => Num++; const ChangeCopy = () => CopyNum++; } return { Num, CopyNum, Change, ChangeCopy }; }; // =>Set operation on key "idx" failed: target is readonly. ``` ### 列表渲染(v-for) 使用 v-for 在要渲染的 DOM 元素上。 :thought_balloon: v-show 透過使用 CSS 中的 display: block / none 來顯示以及隱藏 DOM 元素。 ###### key的重要性: 使用v-for的時候,一定要給 **key**。 :thought_balloon: 使用 v-for 的時候**不要用索引值當 key**,請使用唯一值當作key的值。 ###### 範例: ```htmlmixed= <div id="app"> <ul> <li v-for="(item, idx) in listArr" v-bind:key="item.name" v-show="item.show" > {{item.name}} </li> </ul> </div> ``` ```javascript= const { reactive } = Vue; const App = { setup() { const listArr = reactive([ { name: "2020 Vue3 專業職人 | 入門篇", show: true }, { name: "2020 Vue3 專業職人 | 加值篇", show: false }, { name: "2020 Vue3 專業職人 | 進階篇", show: true }, { name: "現代 JavaScript 職人之路|入門篇", show: true }, { name: "現代 JavaScript 職人之路|中階實戰篇", show: false } ]); } return { listArr }; } ``` ### v-if 與 v-show 如何使用 Vue 來把 DOM 元素做顯示與隱藏。 :thought_balloon: 以上兩者使用情境完全不同,仔細思考應該使用哪一種才可達到目的。 * v-if 隱藏時會直接不做 DOM 元素的渲染,節省渲染的效能。 * v-show 隱藏時會直接套上 display:none; 的CSS屬性,增加切換時的速度。 ###### 範例: ```htmlmixed= <div id="app"> <h1 id="vue-if" v-if="isShow">{{Text}}</h1> <h1 id="vue-show" v-show="isShow">{{Text}}</h1> <button @click="handDomShow">Hand Dom Show</button> </div> ``` ```javascript= const { ref } = Vue; const App = { setup() { const isShow = ref(false); const Text = ref("Hello Vue!"); const handDomShow = () => { isShow.value = !isShow.value; }; return { Text, isShow, handDomShow, }; }, }; Vue.createApp(App).mount("#app"); ``` ### 屬性綁定 (v-bind) 只要是屬性(Attribute),透過使用 v-bind ,都可以動態地把資料塞入,例如: class、src、alt。 :thought_balloon: v-bind 可以使用冒號來縮寫。 ``` v-bind:class="" :class="" ``` ###### 範例(class): ```css= .red { color: red; } .blue { color: blue; } ``` ```htmlmixed= <div id="app"> <ul> <li v-for="(list, idx) in listArr" v-bind:key="list.name" v-bind:class="list.status" > {{idx + 1}}. {{list.name}} </li> </ul> </div> ``` ```javascript= const { reactive } = Vue; const App = { setup() { const listArr = reactive([ { name: "2020 Vue3 專業職人 | 入門篇", status: "red" }, { name: "2020 Vue3 專業職人 | 加值篇", status: "blue" }, { name: "2020 Vue3 專業職人 | 進階篇", status: "red" }, { name: "現代 JavaScript 職人之路|入門篇", status: "red" }, { name: "現代 JavaScript 職人之路|中階實戰篇", status: "blue" }, ]); return { listArr, }; }, }; Vue.createApp(App).mount("#app"); ``` ### 計算屬性 (Computed) 可以靈活的緩存資料,而不需要像是Method一樣,只要資料變化,就需要再呼叫一次。 ### 插槽 (Slot) 可以定義相對的插槽名稱,並將元件或DOM元素指入對應的插槽 ```html= </slot> ``` # 筆記區(尚未整理) * 去除Vue3載入時,出現的大鬍子,要使用**v-clock**,等待所有載入都完成時,才會顯現出來。 * 多多善用Computed,可以靈活的緩存資料,而不需要像是Method一樣,只要資料變化,就需要再呼叫一次。 * readonly 就是讓你的 ref 或是 reactive 的資料只可以讀取不可以被修改,非常適合用在參數傳遞的時候避免不小心被修改資料 ex: const a = readonly(b);