---
# System prepended metadata

title: Vue3 學習筆記

---

# 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);
