跳至主要内容

[Vue] Composition

TL;DR

文章內的程式碼為了可以在codepen上運行,會將一些方法給解構出來。如果使用vite等環境可以要視情況改用ESM的import方式來匯入。

tip

如果想要測試Composition API的程式碼,可以在codepen開啟新專案的地方點選下拉選單,有一個Vue的選項可以直接建立環境

參考資料

相關連結


Composition 簡介

在Options中,我們的邏輯可能會受限於結構,造成明明是同一個業務邏輯,但是資料以及方法卻分散在程式碼的不同地方(例如資料定義在data中,操作資料的方法在methods內),如果需要了解一段邏輯可能需要在程式碼中反覆查找。

而composition可以有效解決這個問題,他的撰寫風格很彈性,我們可以在同一個區塊做到資料定義,按鈕觸發的function的撰寫等等。

但是也因為風格自由,會導致新手無所適從,每個人寫出來的程式碼落差會比較大。所以都會建議還是需要熟悉Options API之後再來撰寫Composition API。

引用六角學院介紹Options API v.s Composition 在程式碼中同業務邏輯區塊的圖片

Options API v.s Composition API

圖片中,左方為Options API,同業務邏輯的區塊分散在程式碼各個區塊中;右方為Composition API,同業務邏輯的區塊在同一個區塊中。

轉換範例

提供一個Options API轉換到Composition API的範例如下:

html part
<div id="app">
{{count}}
<button @click="increment"> + </button>
</div>
js part
const {createApp} = Vue // 解構取出Vue (因為透過CDN,Vue會存在global上)
const APP={
data(){
return{
count:1
}
},
methods:{
increment(){
this.count++
}
}
}
const app=createApp(APP); //已經解構取出fn了,直接使用即可
app.mount('#app');

Codepen Playground

setup?

我們在使用Composition API的時候,所有的程式碼都是撰寫在setup這個function內(使用script setup也一樣)。這個setup function本身就是一個生命週期,會先於Options API的所有其他生命週期,甚至也比beforeCreate還早。

官方的圖示如下: Composition API 生命週期

建立響應式資料

在Options中,我們所需要的資料都可以定義在datafunction 回傳出來。而在Composition中,因為我們的程式碼都會撰寫在setupfunction內,所以我們不需要使用this來取得我們所需要的變數。

Composition有兩種定義響應式資料的方法,分別為:

  1. reactive
  2. ref

reactive

我們可以透過reactive來建立一個Proxy物件。並且透過Proxy來協助我們達到在資料更新時觸發對畫面的重新渲染。

也因為reactive建立的是Proxy物件,所以他傳入的值也一定要是一個物件
p.s:前一篇Proxy中有提到,Proxy的target可以接受物件,包含物件實字、function甚至另一個Proxy物件皆可。

所以接下來,我們就來嘗試一個小範例:

<script setup>
const {reactive} = Vue

const obj={deposit:1000};
const reactiveObj=reactive({myName:'ming'});
const showAlert=(input)=>{
alert(JSON.stringify(input)); // 轉換成字串之後用alert顯示
}
</script>

<template>
obj.deposit:{{obj.deposit}} <br>
<input type="text" v-model="obj.deposit"><br>
<button type="button" @click="showAlert(obj)">without reactive</button>
<hr>
reactiveObj.myName:{{reactiveObj.myName}} <br>
<input type="text" v-model="reactiveObj.myName"> <br>
<button type="button" @click="showAlert(reactiveObj)">with reactive</button>
</template>

Codepen Playground