計(jì)算屬性-computed:僅會(huì)在其響應(yīng)式依賴(lài)更新時(shí)才重新計(jì)算
1募闲、模板中的表達(dá)式雖然方便步脓,但模板中寫(xiě)太多邏輯,會(huì)讓模板變得臃腫浩螺,難以維護(hù)靴患。
2、computed具有緩存作用要出。
<script setup>
import { reactive, computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
})
// 一個(gè)計(jì)算屬性 ref
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
function calculateBooksMessage() {
return author.books.length > 0 ? 'Yes' : 'No'
}
</script>
<template>
// 這么寫(xiě)當(dāng)然也可以鸳君,但是如果頁(yè)面中很多地方需要使用,模板就會(huì)很臃腫
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
<span>{{ publishedBooksMessage }}</span>
// 這么寫(xiě)當(dāng)然也可以患蹂,但是頁(yè)面重新渲染的時(shí)候或颊,方法會(huì)再次調(diào)用,而computed具有緩存作用則不會(huì)
<span>{{ calculateBooksMessage() }}</span>
</template>
偵聽(tīng)器-watch&watchEffect:在每次響應(yīng)式狀態(tài)發(fā)生變化時(shí)觸發(fā)回調(diào)函數(shù)
計(jì)算屬性允許我們聲明性地計(jì)算衍生值传于。然而在有些情況下饭宾,我們需要在狀態(tài)變化時(shí)執(zhí)行一些“副作用”:例如更改 DOM,或是根據(jù)異步操作的結(jié)果去修改另一處的狀態(tài)
- watch
<script setup>
import { ref, watch } from 'vue'
const question = ref('')
const obj = reactive({ count: 0 })
// 可以直接偵聽(tīng)一個(gè) ref
watch(question, async (newval, oldval) => {
// 可以執(zhí)行一些異步操作或者dom更新
const res = await fetch('https://yesno.wtf/api')
})
// 監(jiān)聽(tīng)對(duì)象屬性格了,注意第一個(gè)參數(shù)是一個(gè)方法看铆,切記不可以直接watch obj.count,因?yàn)榈玫降氖莕umber盛末,不具備響應(yīng)式
watch(
() => obj.count,
(count) => {
console.log(`count is: ${count}`)
}
)
// 深度監(jiān)聽(tīng):對(duì)象的屬性(含多層級(jí))發(fā)生改變弹惦,由于需要遍歷嵌套屬性,數(shù)據(jù)結(jié)構(gòu)太深開(kāi)銷(xiāo)會(huì)很大
watch(
() => state.someObject,
(newValue, oldValue) => {
// 注意:`newValue` 此處和 `oldValue` 是相等的
// *除非* state.someObject 被整個(gè)替換了
},
{ deep: true }
)
// 即時(shí)回調(diào)的偵聽(tīng)器:watch是惰性的悄但,僅當(dāng)數(shù)據(jù)源變化時(shí)棠隐,才會(huì)執(zhí)行回調(diào)¢芟可以通過(guò)如下配置立即執(zhí)行
watch(source, (newValue, oldValue) => {
// 立即執(zhí)行助泽,且當(dāng) `source` 改變時(shí)再次執(zhí)行
}, { immediate: true })
</script>
- watchEffect
我認(rèn)為watchEffect可以看做成watch+immediate: true+computed觸發(fā)機(jī)制的合寫(xiě)
// 這里不同的是啰扛,watchEffect第一個(gè)參數(shù)不需要寫(xiě)監(jiān)聽(tīng)的源
// 這個(gè)例子回調(diào)會(huì)立即執(zhí)行,相當(dāng)于immediate: true
watchEffect(async () => {
const response = await fetch(
// 這里有點(diǎn)像computed:每當(dāng) todoId.value 變化時(shí)嗡贺,回調(diào)會(huì)再次執(zhí)行
`https://jsonplaceholder.typicode.com/todos/${todoId.value}`
)
})
- watch vs watchEffect
相同點(diǎn):都能響應(yīng)式地執(zhí)行有副作用的回調(diào)
不同點(diǎn):watch只追蹤明確偵聽(tīng)的數(shù)據(jù)源隐解,比如說(shuō)我監(jiān)聽(tīng)obj,只能監(jiān)聽(tīng)obj的屬性變化诫睬,但是watchEffect里面既可以監(jiān)聽(tīng)obj的屬性變化煞茫,也可以監(jiān)聽(tīng)其他對(duì)象的屬性變化。簡(jiǎn)單說(shuō)摄凡,watch追蹤更加明確续徽,而watchEffect則不太明確。 - 回調(diào)的觸發(fā)時(shí)機(jī)
當(dāng)你更改了響應(yīng)式狀態(tài)亲澡,它可能會(huì)同時(shí)觸發(fā) Vue 組件更新和偵聽(tīng)器回調(diào)钦扭。默認(rèn)情況下,偵聽(tīng)器回調(diào)的觸發(fā)在DOM更新之前床绪,這意味著你在偵聽(tīng)器回調(diào)中訪問(wèn)的 DOM 將是被 Vue 更新之前的狀態(tài)客情。如果想在偵聽(tīng)器回調(diào)中能訪問(wèn)被 Vue 更新之后的 DOM,可通過(guò)如下配置:
watch(source, callback, {
flush: 'post'
})
watchEffect(callback, {
flush: 'post'
})
// 后置刷新的 watchEffect() 有個(gè)更方便的別名 watchPostEffect()
import { watchPostEffect } from 'vue'
watchPostEffect(() => {
/* 在 Vue 更新后執(zhí)行 */
})
- 停止偵聽(tīng)器
const unwatch = watchEffect(() => {})
// ...當(dāng)該偵聽(tīng)器不再需要時(shí)
unwatch()