---
# System prepended metadata

title: Vue Composition API
tags: [Vue.js]

---

---
tags: Vue.js
---

# Vue Composition API

## 你需要先知道的事

Composition API 是 vue3 開發出來的另外一種撰寫方法。

其好處是: 
  1. `setup()` 方法中沒有 `this`
  2. `setup()` 方法中可以只 `return` 實例需要用到的屬性
  3. 沒有命名衝突問題
  4. 其編譯後的程式碼更容易壓縮

另外建議使用 Composition API 都用 ESM 方式引入不要用 CDN 整包引入(ESM 跟 CDN 一次只選用一種，不要兩種都用)

在 `Composition API` 中 `data` `methods` `mounted` 都會捨棄，改寫成一個 `setup(){ return {}; }`

## 撰寫方式

創建一個 `html` 檔 並在 `body` 標籤中創建 `div#app` 在 `body` 最下面寫 `script` 代碼

首先使用 `ESM` 方式引入 `vue` 中的 `createApp`

接下來使用 `const` 聲明 `app` 為一個物件

物件中放入一個 `setup` 的函數 在裡面撰寫程式碼

最後通過 `app.mount('#app')` 創建整個 `vue` 實例

整個示例主要的 script 代碼如下：

```javascript=
import { createApp, ref } from "https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.11/vue.esm-browser.js";

const app = createApp({
  setup() {
    const text = ref('Hello World'); // 這裡等同於 data

    const changeText = () => { // 這裡等同於 methods
      text.value = 'Hello Vue';
    }

    return { // 宣告完後要用 return 才會渲染
      text,
      changeText
    }
  }
})

app.mount('#app');
```

## `ref` vs `reactive`

- ref 可用於變數物件或陣列等，總之就是不限型別，其內部還是調用 reactive
- reactive 只能用於物件，建議把有關聯的數據放在同一個對象裏提高代碼的可讀性（不熟的話先不要用，reactive 很多雷點）
- reactive 如果被解構賦值的話，裏面的東西會失去雙向綁定的特性，此時可以通過 toRefs 把物件裏面的每個屬性轉成 ref 來延續使用
- ref 定義的東西一定要用 .value 才可監控與獲取哦（多了 .value 就不會覆蓋到原始實體，相對來說會比較穩定）
- 了解更多請參考以下關鍵字：Proxy、getter、setter、defineproperty
- ref 用於物件時 在存取屬性也要加上 `.value` (EX: `person.value.name` .value 要放在物件的後面&屬性前面 小寫別寫錯喔)
- 建議初學者都是一路 const + ref 把 data 宣告到底（畢竟有雷別踩R~）
    - 建議使用 const 是要避免覆蓋，因為常數不能重新賦值（會報錯）

## `watch` vs `computed`

`vue` 中的 `watch` `computed` 可以單獨被拿出來使用

提取方法同上面的 `ref` 相同 直接通過解構方式即可(就是 `import { watch, computed } from "vue ESM URL";` 這樣)

在 `setup` 中要使用 `watch` `computed` 不需要像 `ref` `reactive` 一樣通過 `const` 定義

只需要直接寫 `watch()` `computed()` 即可，不過跟原本在 `vue` 實例中的寫法也稍有不同

首先 `watch` 的參數1 為 要監控的資料 `dataName`

  * 當要監控的資料為陣列或物件中的單一值 為了減輕效能 可以不需要把整個陣列或物件傳入 改成使用箭頭函式 `return` 該單一值
    - 這裏 `return` 可以讓它繼續被監控 
  * 需注意 若沒有使用 `return` 則該值就只是一個字符串 跟 `vue` 不會有任何綁定關係

參數2 為一個 `callback`，在 `callback` 中則一樣有 `newV` 與 `oldV`

這邊我們定義一個要監控的資料並把其傳入 `watch` 的參數1

再通過 `v-on` 更改其值 就會執行 `watch` 中的回調函數了

代碼如下：

```javascript=
import { createApp, ref, watch } from "https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.11/vue.esm-browser.js";

const app = createApp({
  setup(){
    const isShow = ref(false)
    const formData = reactive({ name:'', age:10 })

    const changeData = () => {
      isShow.value = !isShow.value
      formData.age = 19
    }

    watch(isShow, (newV,oldV) => {
      console.log(newV, oldV)
    })

    // 監控物件中的單一值
    watch(() => formData.age, ( newV, oldV ) => {
      console.log(newV, oldV)
    })

    return { isShow, changeData }
  }
})

app.mount('#app')
```

`computed` 寫法就跟原本差不多 只需注意若要計算的值是用 ref 定義的 需加上 `.value`

```javascript=
import { createApp, ref, watch, computed } from "https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.11/vue.esm-browser.js";

const app = createApp({
  setup(){
    const num = ref(1)

    const dblNum = computed(() => {
      return num.value * 2
    })

    return { num, dblNum }
  }
})

app.mount('#app')
```

## `mounted`

mounted 在 Composition API 中要改寫成 onMounted 同一個 setup 中可以一次擁有多個 onMounted

比如以邏輯的思路把每個資料區域由上至下獨立分開設置

原本的寫法是必須把資料統一寫在 data 或 methods 或 mounted

Composition API 可以變成你想要哪些東西是有關聯性就寫在一起
不需要再強制性把東西都放在 data 或 methods 或 mounted

比如你要操作 text 相關的從 ref ，到 methods 的函數，到他的初始化都可以寫在最上方 接著下方就統一寫另一個假設是 num 相關的操作

在閱讀程式碼時可讀性會比較高 這也是其好處之一 所以可以多次重複調用 onMounted

