Vue3 composition API option API差異(1/n):ref, reactive, computed

Wendy Chang
Wendy Loops
Published in
10 min readMar 23, 2023

Vue3開始支援composition API,但同時也支援Vue2的option API,我自己在接觸Vue時,雖然是使用Vue3,但還是用option API的寫法,直到最近到了新公司,發現Vue3就是要用composition API拉!好8學無止境只能再次打開筆記本ㄌ。

這次示範了同一件事情,用option API寫跟用composition API寫的差別,之後應該會覺得composition API真香。

Option API

根據程式功能來區分程式碼:

export default{
props: {},
components: {},
data() {
// 所有資料
},
computed() {
// 點擊增加資料
},
mounted() {
// axios取得資料
},
methods() {
// 刪除資料
}
}

一個功能可能會被切割到methods、computed中,不易維護也不方便閱讀。

Composition API

export default {
setup() {
// 所有資料...
// 取得資料...
// 增加資料...
// 刪除資料...
}
}

data( ) 預設值

Option API

<template lang="">
<div>
<h2>{{name}}</h2>
</div>
</template>

<script>
export default {
data(){
return {
name: 'wendy'
}
}
}
</script>

Composition API

把函數寫在setup()中,用const接收預設值,最後在底端把name return出去。

<template lang="">
<div>
<h2>{{ name }}</h2>
</div>
</template>

<script>
export default {
setup(){
const name = 'wendy'
return { name }
}
}
</script>

v-model

Option API

<template lang="">
<div>
<input type="text" v-model="name">
<h2>{{name}}</h2>
</div>
</template>
<script>

export default {
data(){
return {
name:''
}
}
}
</script>

Composition API

  1. import ref 進來
  2. 注意name後方的寫法
  3. name return出去
<template lang="">
<div>
<input type="text" v-model="name">
<h2>{{name}}</h2>
</div>
</template>

<script>
import { ref } from 'vue'
export default {
setup(){
const name = ref(null)
return { name }
}
}

</script>

🍬setup語法糖

如果覺得export default的寫法太囉嗦,也可以這樣寫:

<template lang="">
<div>
<h2>{{name}}</h2>
</div>
</template>

<script setup>
import { ref, computed } from 'vue'
const name = computed(() => {
return 'Kelly'
})
</script>

就不用再把const出來的變數return出去了,同理如果有import component,用這種寫法就不用再定義component:{ }了。

另外這個只有Vue3可以用,Vue2不能使用。

ref( )

Composition API

ref()是一個函數,可以接收任何型別的參數,並回傳響應式可變動的物件。以下示範把input框內的文字丟到alert上去。

  1. 接收click事件的按鈕
  2. 用const把事件函數包起來,取得ref內的資料要用.value去取。
  3. 把事件函數handler return出去
<template lang="">
<div>
<input type="text" v-model="name">
<h2>{{ name }}</h2>
<button @click="handler">click</button>
</div>
</template>

<script>

import { ref } from 'vue'

export default {
setup(){
const name = ref('wendy')
const handler = ()=>{
alert(name.value)
}
return { name, handler }
}
}

</script>

會使用const來包,是避免我們在要改變值時,忘記加上.value,如果今天用let的話,就會很難debug:

export default {
setup(){
let name = ref('wendy')
const handler = ()=>{
name = 'sandy'
console.log(name)
}
return { name, handler }
}
}

畫面會出現wendy,而console.log會出現sandy現在就是把name用sandy這個String去取代了,而不是原本的ref,而let的性質使程式不會報錯,所以這裡還是盡量使用const比較好。

JavaScript面試題:var let const的差別

option API

  1. 預設值跟methods要分開寫
  2. methods內的函數要取最新的name,要用this去取
<template lang="">
<div>
<input type="text" v-model="name">
<h2>{{name}}</h2>
<button @click="handler">click</button>
</div>
</template>

<script>
export default {
data(){
return {
name:'wendy'
}
},
methods: {
handler(){
alert(this.name)
}
}
}
</script>

reactive( )

ref很像的就是reactive(),兩者同樣具備響應式功能,而reactive()中只能放陣列或物件,並且不需要.value來做取用。

<template lang="">
<div>
<h2>{{data.name}}</h2>
<h2>{{data.age}}</h2>
<h2>{{data.address}}</h2>
</div>
</template>

<script setup>
import { ref, computed,reactive } from 'vue'

const data = reactive({
name: 'wendy',
age: 18,
address: 'Taiwan'
})

//兩秒後會置換
setTimeout(()=>{
data.name = 'sandy'
data.age = '16'
data.address = 'Taipei'
},2000)

</script>

watch( )監聽

講到ref()reactive()的差別就一定要提到watch監聽,watch可以用來監聽reactive()內容有沒有改變,而不會監聽到ref的改變。

watch(要監聽的物件, 回呼函式)

<template lang="">
<div>
<h2>{{people1.name}}</h2>
<h2>{{people2.name}}</h2>
</div>
</template>
<script setup>
import { ref, computed,reactive,watch } from 'vue'

const people1 = ref({
name: 'kevin'
})

const people2 = reactive({
name: 'kyle'
})

setTimeout(()=>{
people1.value.name = 'newKevin'
people2.name = 'newKyle'
},2000)

watch(people1,()=>{
console.log('people1 被改變了');
})

watch(people2,()=>{
console.log('people2 被改變了');
})
</script>
只有reactive的people2監聽得到

如果想要讓ref()被watch到,那就要在watch()中加入第三個參數{deep: true}

watch(people1,()=>{
console.log('people1 被改變了');
},{deep: true})
ref的people1也能被監聽到了

computed( )計算屬性

就是會return 一個值出去的那個,面試超愛考computed、methods、watch的差異。

option API

<template lang="">
<div>
<h2>{{newname}}</h2>
</div>
</template>

<script>
export default {
data() {
return {
name: 'wendy'
}
},
computed: {
newname(){
return this.name = 'sandy'
}
}
}
</script>

網頁會呈現sandy

Composition API

<template lang="">
<div>
<h2>{{name}}</h2>

</div>
</template>

<script>
import { ref, computed } from 'vue'
export default {
setup() {
const name = computed(() => {
return 'Kelly'
})
return { name }
}
}
</script>

網頁會呈現Kelly

--

--

Wendy Chang
Wendy Loops

什麼都寫ㄉ前端工程師 / 影片剪輯師 / 自媒體經營者