Vue3之計(jì)算屬性與偵聽(tīng)器

計(jì)算屬性-computed:僅會(huì)在其響應(yīng)式依賴更新時(shí)才重新計(jì)算

1、模板中的表達(dá)式雖然方便,但模板中寫太多邏輯,會(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>
  // 這么寫當(dāng)然也可以,但是如果頁(yè)面中很多地方需要使用,模板就會(huì)很臃腫
  <span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
  <span>{{ publishedBooksMessage }}</span>
  // 這么寫當(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)銷會(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ī)制的合寫
// 這里不同的是,watchEffect第一個(gè)參數(shù)不需要寫監(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()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容