除了使用 computed()
為特定 State 加工外,Vue 還提供 watch()
可追蹤特定 State 處理 Side Effect,尤其 呼叫 API
就是典型的 Side Effect。
Version
Vue 3.4
Composition API
<template>
<div>
Ask a yes/no question:
<input v-model="question" :disabled="loading" />
</div>
<div>{{ answer }}</div>
</template>
<script setup>
import { ref, watch } from 'vue'
let question = ref('')
let answer = ref('Questions usually contain a question mark. ;-)')
let loading = ref(false)
watch(question, async (newValue) => {
if (newValue.includes('?')) {
loading.value = true
answer.value = 'Thinking...'
try {
let res = await fetch('https://yesno.wtf/api')
answer.value = (await res.json()).answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
} finally {
loading.value = false
}
} else {
answer.value = 'Questions usually contain a question mark. ;-)'
}
})
</script>
Line 2
<div>
Ask a yes/no question:
<input v-model="question" :disabled="loading" />
</div>
<div>{{ answer }}</div>
- User 輸入問題
- 下方顯示 API 回傳答案
Line 12
let question = ref('')
let answer = ref('Questions usually contain a question mark. ;-)')
let loading = ref(false)
- question state:儲存問題
- answer state:儲存 API 回傳答案
- loading state:儲存 API 回傳狀態
Line 16
watch(question, async (newValue) => {
})
watch()
:追蹤count
state,當count
state 一有變動,就會執行傳入 function- 傳入 function 可接受兩個參數:
newValue
與oldValue
Line 17
if (newValue.includes('?')) {
loading.value = true
answer.value = 'Thinking...'
try {
let res = await fetch('https://yesno.wtf/api')
answer.value = (await res.json()).answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
} finally {
loading.value = false
}
} else {
answer.value = 'Questions usually contain a question mark. ;-)'
}
- 若輸入問題包含
?
,則呼叫 API 並顯示結果,否則繼續顯示提示
- 呼叫 API 就是典型的 Side Effect
Options API
<template>
<div>
Ask a yes/no question:
<input v-model="question" :disabled="loading" />
</div>
<div>{{ answer }}</div>
</template>
<script>
export default {
data: () => ({
question: '',
answer: 'Questions usually contain a question mark. ;-)',
loading: false
}),
watch: {
async question(newValue) {
if (newValue.includes('?')) {
this.loading = true
this.answer = 'Thinking...'
try {
let res = await fetch('https://yesno.wtf/api')
this.answer = (await res.json()).answer
} catch (error) {
this.answer = 'Error! Could not reach the API. ' + error
} finally {
this.loading = false
}
} else {
this.answer = 'Questions usually contain a question mark. ;-)'
}
}
}
}
</script>
- 最後附上相同功能的 Options API 供參考
- State 宣告在
data()
function watch()
function 改成watch
Object,將要偵測的 state 以 method 命名
Conclusion
- Watch 在 Options API 與 Composition API 下有顯著差異
- Watch 在 Options API 是以 method 形式宣告在
watch
Object 下 - Watch 在 Composition API 是以 function 傳入
watch()