溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Vue中的Computed與watch怎么用

發(fā)布時間:2022-04-29 10:19:33 來源:億速云 閱讀:205 作者:iii 欄目:開發(fā)技術(shù)

這篇“Vue中的Computed與watch怎么用”文章的知識點大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Vue中的Computed與watch怎么用”文章吧。

computed

computed只接收一個getter函數(shù)

1、getter必須有返回值

2、computed返回一個只讀響應(yīng)式ref對象 (只讀、響應(yīng)式、對象)

注意:omputed只接收一個getter函數(shù)時,返回的只讀對象,也就是不能修改他的返回值!

getter觸發(fā)條件

  • 1、computed返回值首次被讀取時

  • 2、getter綁定的響應(yīng)式變量被修改時

<script setup>
import { ref,computed } from 'vue'
const num = ref(1)
//computed返回一個只讀響應(yīng)式ref對象computedNum
//computedNum是只讀屬性
let computedNum = computed(() => num.value + 1)
</script>

<template>
    <p> num:{{ num }} </p>
    <p>computedNum:{{ computedNum }}</p>
    <!-- 修改響應(yīng)式變量num 觸發(fā)與之綁定的computed的getter-->  
    <button @click="num++">num++</button>
    <!-- computedNum是只讀屬性-->  
    <button @click="computedNum++">computedNum++</button>
</template>

computed同時接收getter函數(shù)對象和setter函數(shù)對象

1、setter函數(shù)對象沒有返回值

2、computed返回一個可讀可寫響應(yīng)式對象

3、setter函數(shù)對象有參數(shù),是getter的返回值,也是computed的值

4、修改computed返回值,觸發(fā)setter函數(shù)對象執(zhí)行,但不會真正修改computed返回值(setter內(nèi)改變getter計算值就會改變computed返回值)

setter觸發(fā)條件

computed返回值被修改時

實例:

<script setup>
import { ref, computed } from 'vue'
const num = ref(1)
//getter(只讀)
let computedNum = computed(() => num.value + 1)
//getter和setter (可讀可寫)
let computedNum2 = computed({
    get: () => num.value + 1,
    set: (val) => {
         console.log(val);
        //setter中修改ref響應(yīng)式變量num,將觸發(fā)關(guān)聯(lián)的num的getter計算
        //computedNum和computedNum2的getter同時觸發(fā)
         num.value++
          }
})
</script>

<template>
    <p> num:{{ num }} </p>
    <p>computedNum:{{ computedNum }}</p>
    <p>computedNum2:{{ computedNum2 }}</p>
    <button @click="num++">num++</button>
    <!-- computedNum是只讀屬性,會有警告提醒 Write operation failed: computed value is readonly-->  
    <button @click="computedNum++">computedNum++</button>
     <!-- computedNum2是可讀可寫屬性-->  
    <button @click="computedNum2++">computedNum2++</button>
</template>

調(diào)試 Computed

使用范圍:僅開發(fā)模式生效

computed的第二參數(shù):帶有 onTrackonTrigger 選項的對象

  • onTrack :getter關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)時觸發(fā)。

  • onTrigger :getter關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)被修改時觸發(fā)

<script setup>
import { ref, computed } from 'vue'
const num = ref(1)
let computedNum = computed(() => num.value + 1, {
    onTrack: (e) => {
        console.log('onTrack');
        console.log(e);
    },
    onTrigger: (e) => {
        console.log('onTrigger');
        console.log(e);
    }
})

</script>

<template>
    <p> num:{{ num }} </p>
    <p>computedNum:{{ computedNum }}</p>
    <!--每次 num++將觸發(fā)onTrigger -->
    <button @click="num++">num++</button>
</template>

watchEffect

語法:

  • 參數(shù)1:觸發(fā)監(jiān)聽回調(diào)函數(shù),回調(diào)函數(shù)可傳入一個onInvalidate函數(shù)作為參數(shù)!

  • 可選參數(shù)2:對象,包含3個可選屬性flush、onTrack、onTrigger

立即執(zhí)行傳入的一個函數(shù),同時響應(yīng)式追蹤其依賴,并在其依賴變更時重新運行該函數(shù)。

1、會立即執(zhí)行一次(和watch的immediate屬性效果一致)

2、關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)被修改時觸發(fā)

3、會自動感知代碼依賴,和watch不一樣,watchEffect會主動綁定監(jiān)聽數(shù)據(jù)

局限性:不能監(jiān)聽對象(但可以監(jiān)聽對象的屬性),只能監(jiān)聽類似ref基本數(shù)據(jù)類型的響應(yīng)式數(shù)據(jù)

立即執(zhí)行 監(jiān)聽基本數(shù)據(jù)類型

<script setup>
import { ref, watchEffect } from 'vue'
const num = ref(1)
//會立即執(zhí)行一次
watchEffect(() => {
    console.log('watchEffect');
    num.value++
})
</script>

<template>
    <p>num: {{ num }}</p>
    <button @click="num++">num++</button>
</template>

停止watchEffect

隱式:組件卸載時自動停止

顯式:調(diào)用watchEffect 返回值

const stop = watchEffect(() => {
  /* ... */
})

// 顯式停止
stop()

清理watchEffect

語法: watchEffect( onInvalidate=>{ onInvalidate(()=>{ }) })

onInvalidate 是一個函數(shù)!優(yōu)先觸發(fā)!

onInvalidate 執(zhí)行時機:

1、watchEffect被重新觸發(fā)時

2、組件卸載時

注意:關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)首次被修改時不會觸發(fā)onInvalidate函數(shù)!

作用: 清理定時器、事件監(jiān)聽removeEventListener 。。。

import { ref, watchEffect } from 'vue'
const num = ref(1)
watchEffect((onInvalidate ) => {
    console.log('watchEffect-1');
    num.value++
    onInvalidate (()=>{
        console.log('onInvalidate-2');
    })
    console.log('watchEffect-3');
})

//1、watchEffect   被重新觸發(fā)時
// onInvalidate-2
// watchEffect-1
// watchEffect-3
//2、組件卸載時
// onInvalidate-2
//3、關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)首次被修改(組件被掛載時)
//  watchEffect-1
//  watchEffect-3

watchPostEffect 和 watchSyncEffect

watchPostEffectwatchSyncEffect在Vue3.2新增,是watchEffect類似語法糖的東西,

watchEffect可選參數(shù)對象{ flush?: 'pre' | 'post' | 'sync'}中post和sync的語法糖,pre是默認值

推遲觸發(fā)watchPostEffect

watchPostEffect 是watchEffect可選參數(shù)對象{flush:'post'}的語法糖

推遲watchEffect觸發(fā)時機!組件更新前觸發(fā)!也就是在生命周期onBeforeUpdateonUpdated之間觸發(fā)

語法:

//推遲觸發(fā)watchEffect
watchEffect(
  () => {
    /* ... */
  },
  {
    flush: 'post'
  }
)
//Vue3.2語法糖watchPostEffect
watchPostEffect(()=>{
  /* ... */
})

實例:

//實驗watchEffect第二參數(shù) flush: 'post'屬性
watchEffect(() => {
    console.log("實驗watchEffect第二參數(shù) {flush: 'post'}屬性");
    console.log(obj.age);
},{
   flush:'post' 
})
watchEffect(() => {
    console.log("watchEffect正常時機觸發(fā)");
    console.log(obj.age);
})
//生命周期onUpdated
onUpdated(()=>{
    console.log('onUpdated()');  
})
//生命周期onBeforeUpdate
onBeforeUpdate(()=>{
    console.log('onBeforeUpdate()');
})

修改obj.age時,執(zhí)行結(jié)果:

watchEffect正常時機觸發(fā)
onBeforeUpdate()
實驗watchEffect第二參數(shù) {flush: 'post'}屬性
onUpdated()

同步觸發(fā)watchSyncEffect

watchSyncEffect 是watchEffect可選參數(shù)對象{flush:'sync'}的語法糖

強制效果始終同步觸發(fā)!效率低!也就是默認watchEffect之前觸發(fā)

語法:

watchEffect(
  () => {
    /* ... */
},
  {
    flush: 'sync'
  }
)
//Vue3.2語法糖watchSyncEffect
watchSyncEffect(()=>{
  /* ... */
})

watchEffect不能監(jiān)聽對象

//假設(shè)修改了對象的屬性值-修改了obj.age
const obj = reactive({ name: '小明', age: 18 })
//watchEffect不能監(jiān)聽對象變化
watchEffect(() => {
    console.log('watchEffect監(jiān)聽對象變化');
    console.log(obj);
})
//watchEffect可以監(jiān)聽對象屬性變化
watchEffect(() => {
    console.log('watchEffect監(jiān)聽對象屬性變化');
    console.log(obj.age);
})
//watch監(jiān)聽對象變化
watch(obj, (obj) => {
    console.log('watch監(jiān)聽對象變化');
    console.log(obj);
})

總結(jié):watchEffect用來監(jiān)聽能監(jiān)聽基本數(shù)據(jù)類型,不能監(jiān)聽對象,但能監(jiān)聽對象的屬性;watch能監(jiān)聽基本數(shù)據(jù)類型和對象!

watch

語法:

  • 參數(shù)1-被監(jiān)聽數(shù)據(jù)(形式:單個數(shù)據(jù)、數(shù)組、帶返回值的回調(diào)函數(shù))

  • 參數(shù)2-觸發(fā)監(jiān)聽的回調(diào)函數(shù),無返回值

  • 可選參數(shù)3-對象{immediate: true,deep:true},對象含2個可選參數(shù)和Vue2參數(shù)效果一致

Vue3的watch和Vue2的watch是基本一樣的

1、需要指定監(jiān)聽數(shù)據(jù)

2、惰性,只在被監(jiān)聽數(shù)據(jù)變化時才觸發(fā)(immediate屬性可以設(shè)置在初始化的時候觸發(fā))

監(jiān)聽單個數(shù)據(jù)

參數(shù)1被監(jiān)聽數(shù)據(jù)的形式:

1、單個基本數(shù)據(jù)類型;

2、回調(diào)函數(shù):返回值為單個基本數(shù)據(jù)類型;

// 偵聽一個 getter
//被監(jiān)聽數(shù)據(jù)傳入一個帶返回值的回調(diào)函數(shù)
const state = reactive({ count: 0 })
watch(
  () => state.count,
  (count, prevCount) => {
    /* ... */
  }
)

// 直接偵聽一個 ref
const count = ref(0)
watch(count, (count, prevCount) => {
  /* ... */
})

監(jiān)聽多個數(shù)據(jù)(傳入數(shù)組)

watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
  /* ... */
})

官方文檔總結(jié)

以下代碼截取官方文檔,從TS代碼可以看出很多關(guān)于watch和watchEffect函數(shù)參數(shù)和返回值的細節(jié)!

computed

computed只接收一個getter函數(shù)

getter觸發(fā)條件:

1、computed返回值首次被讀取時

2、getter綁定的響應(yīng)式變量被修改時

computed同時接收getter函數(shù)對象和setter函數(shù)對象

setter觸發(fā)條件:computed返回值被修改時

// 只讀的
function computed<T>(
  getter: () => T,
  debuggerOptions?: DebuggerOptions
): Readonly<Ref<Readonly<T>>>

// 可寫的
function computed<T>(
  options: {
    get: () => T
    set: (value: T) => void
  },
  debuggerOptions?: DebuggerOptions
): Ref<T>
interface DebuggerOptions {
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
}
interface DebuggerEvent {
  effect: ReactiveEffect
  target: any
  type: OperationTypes
  key: string | symbol | undefined
}

watchEffect

  • 參數(shù)1-觸發(fā)監(jiān)聽回調(diào)函數(shù),回調(diào)函數(shù)可傳入一個onInvalidate函數(shù)作為參數(shù)!

  • 可選參數(shù)2-對象,包含3個可選屬性flush、onTrack、onTrigger

function watchEffect(
  effect: (onInvalidate: InvalidateCbRegistrator) => void,
  options?: WatchEffectOptions
): StopHandle

interface WatchEffectOptions {
  flush?: 'pre' | 'post' | 'sync' // 默認:'pre'
  onTrack?: (event: DebuggerEvent) => void
  onTrigger?: (event: DebuggerEvent) => void
}

interface DebuggerEvent {
  effect: ReactiveEffect
  target: any
  type: OperationTypes
  key: string | symbol | undefined
}

type InvalidateCbRegistrator = (invalidate: () => void) => void

type StopHandle = () => void

watch

  • 參數(shù)1-被監(jiān)聽數(shù)據(jù)(形式:單個數(shù)據(jù)、數(shù)組、帶返回值的回調(diào)函數(shù))

  • 參數(shù)2-觸發(fā)監(jiān)聽的回調(diào)函數(shù),無返回值

  • 參數(shù)3-傳入{immediate: true,deep:true}對象和Vue2參數(shù)效果一致

// 偵聽單一源
function watch<T>(
  source: WatcherSource<T>,
  callback: (
    value: T,
    oldValue: T,
    onInvalidate: InvalidateCbRegistrator
  ) => void,
  options?: WatchOptions
): StopHandle

// 偵聽多個源
function watch<T extends WatcherSource<unknown>[]>(
  sources: T
  callback: (
    values: MapSources<T>,
    oldValues: MapSources<T>,
    onInvalidate: InvalidateCbRegistrator
  ) => void,
  options? : WatchOptions
): StopHandle

type WatcherSource<T> = Ref<T> | (() => T)

type MapSources<T> = {
  [K in keyof T]: T[K] extends WatcherSource<infer V> ? V : never
}

// 參見 `watchEffect` 共享選項的類型聲明
interface WatchOptions extends WatchEffectOptions {
  immediate?: boolean // 默認:false
  deep?: boolean
}

以上就是關(guān)于“Vue中的Computed與watch怎么用”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對大家有幫助,若想了解更多相關(guān)的知識內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI