詳解Vue中Computed與watch的用法與區(qū)別
computed
computed只接收一個(gè)getter函數(shù)
1、getter必須有返回值
2、computed返回一個(gè)只讀響應(yīng)式ref對(duì)象 (只讀、響應(yīng)式、對(duì)象)
注意:omputed只接收一個(gè)getter函數(shù)時(shí),返回的只讀對(duì)象,也就是不能修改他的返回值!
getter觸發(fā)條件
- 1、computed返回值首次被讀取時(shí)
- 2、getter綁定的響應(yīng)式變量被修改時(shí)
<script setup>
import { ref,computed } from 'vue'
const num = ref(1)
//computed返回一個(gè)只讀響應(yīng)式ref對(duì)象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同時(shí)接收getter函數(shù)對(duì)象和setter函數(shù)對(duì)象
1、setter函數(shù)對(duì)象沒有返回值
2、computed返回一個(gè)可讀可寫響應(yīng)式對(duì)象
3、setter函數(shù)對(duì)象有參數(shù),是getter的返回值,也是computed的值
4、修改computed返回值,觸發(fā)setter函數(shù)對(duì)象執(zhí)行,但不會(huì)真正修改computed返回值(setter內(nèi)改變getter計(jì)算值就會(huì)改變computed返回值)
setter觸發(fā)條件
computed返回值被修改時(shí)
實(shí)例:
<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計(jì)算
//computedNum和computedNum2的getter同時(shí)觸發(fā)
num.value++
}
})
</script>
?
<template>
<p> num:{{ num }} </p>
<p>computedNum:{{ computedNum }}</p>
<p>computedNum2:{{ computedNum2 }}</p>
<button @click="num++">num++</button>
<!-- computedNum是只讀屬性,會(huì)有警告提醒 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ù):帶有 onTrack 和 onTrigger 選項(xiàng)的對(duì)象
onTrack:getter關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)時(shí)觸發(fā)。onTrigger:getter關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)被修改時(shí)觸發(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ù)可傳入一個(gè)onInvalidate函數(shù)作為參數(shù)!
- 可選參數(shù)2:對(duì)象,包含3個(gè)可選屬性flush、onTrack、onTrigger
立即執(zhí)行傳入的一個(gè)函數(shù),同時(shí)響應(yīng)式追蹤其依賴,并在其依賴變更時(shí)重新運(yùn)行該函數(shù)。
1、會(huì)立即執(zhí)行一次(和watch的immediate屬性效果一致)
2、關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)被修改時(shí)觸發(fā)
3、會(huì)自動(dòng)感知代碼依賴,和watch不一樣,watchEffect會(huì)主動(dòng)綁定監(jiān)聽數(shù)據(jù)
局限性:不能監(jiān)聽對(duì)象(但可以監(jiān)聽對(duì)象的屬性),只能監(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)
//會(huì)立即執(zhí)行一次
watchEffect(() => {
console.log('watchEffect');
num.value++
})
</script>
?
<template>
<p>num: {{ num }}</p>
<button @click="num++">num++</button>
</template>停止watchEffect
隱式:組件卸載時(shí)自動(dòng)停止
顯式:調(diào)用watchEffect 返回值
const stop = watchEffect(() => {
/* ... */
})
?
// 顯式停止
stop()清理watchEffect
語法: watchEffect( onInvalidate=>{ onInvalidate(()=>{ }) })
onInvalidate 是一個(gè)函數(shù)!優(yōu)先觸發(fā)!
onInvalidate 執(zhí)行時(shí)機(jī):
1、watchEffect被重新觸發(fā)時(shí)
2、組件卸載時(shí)
注意:關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)首次被修改時(shí)不會(huì)觸發(fā)onInvalidate函數(shù)!
作用: 清理定時(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ā)時(shí)
// onInvalidate-2
// watchEffect-1
// watchEffect-3
//2、組件卸載時(shí)
// onInvalidate-2
//3、關(guān)聯(lián)的響應(yīng)式數(shù)據(jù)首次被修改(組件被掛載時(shí))
// watchEffect-1
// watchEffect-3watchPostEffect 和 watchSyncEffect
watchPostEffect 和 watchSyncEffect在Vue3.2新增,是watchEffect類似語法糖的東西,
是watchEffect可選參數(shù)對(duì)象{ flush?: 'pre' | 'post' | 'sync'}中post和sync的語法糖,pre是默認(rèn)值
推遲觸發(fā)watchPostEffect
watchPostEffect 是watchEffect可選參數(shù)對(duì)象{flush:'post'}的語法糖
推遲watchEffect觸發(fā)時(shí)機(jī)!組件更新前觸發(fā)!也就是在生命周期onBeforeUpdate和 onUpdated之間觸發(fā)
語法:
//推遲觸發(fā)watchEffect
watchEffect(
() => {
/* ... */
},
{
flush: 'post'
}
)
//Vue3.2語法糖watchPostEffect
watchPostEffect(()=>{
/* ... */
})實(shí)例:
//實(shí)驗(yàn)watchEffect第二參數(shù) flush: 'post'屬性
watchEffect(() => {
console.log("實(shí)驗(yàn)watchEffect第二參數(shù) {flush: 'post'}屬性");
console.log(obj.age);
},{
flush:'post'
})
watchEffect(() => {
console.log("watchEffect正常時(shí)機(jī)觸發(fā)");
console.log(obj.age);
})
//生命周期onUpdated
onUpdated(()=>{
console.log('onUpdated()');
})
//生命周期onBeforeUpdate
onBeforeUpdate(()=>{
console.log('onBeforeUpdate()');
})修改obj.age時(shí),執(zhí)行結(jié)果:
watchEffect正常時(shí)機(jī)觸發(fā)
onBeforeUpdate()
實(shí)驗(yàn)watchEffect第二參數(shù) {flush: 'post'}屬性
onUpdated()
同步觸發(fā)watchSyncEffect
watchSyncEffect 是watchEffect可選參數(shù)對(duì)象{flush:'sync'}的語法糖
強(qiáng)制效果始終同步觸發(fā)!效率低!也就是默認(rèn)watchEffect之前觸發(fā)
語法:
watchEffect(
() => {
/* ... */
},
{
flush: 'sync'
}
)
//Vue3.2語法糖watchSyncEffect
watchSyncEffect(()=>{
/* ... */
})watchEffect不能監(jiān)聽對(duì)象
//假設(shè)修改了對(duì)象的屬性值-修改了obj.age
const obj = reactive({ name: '小明', age: 18 })
//watchEffect不能監(jiān)聽對(duì)象變化
watchEffect(() => {
console.log('watchEffect監(jiān)聽對(duì)象變化');
console.log(obj);
})
//watchEffect可以監(jiān)聽對(duì)象屬性變化
watchEffect(() => {
console.log('watchEffect監(jiān)聽對(duì)象屬性變化');
console.log(obj.age);
})
//watch監(jiān)聽對(duì)象變化
watch(obj, (obj) => {
console.log('watch監(jiān)聽對(duì)象變化');
console.log(obj);
})總結(jié):watchEffect用來監(jiān)聽能監(jiān)聽基本數(shù)據(jù)類型,不能監(jiān)聽對(duì)象,但能監(jiān)聽對(duì)象的屬性;watch能監(jiān)聽基本數(shù)據(jù)類型和對(duì)象!
watch
語法:
- 參數(shù)1-被監(jiān)聽數(shù)據(jù)(形式:?jiǎn)蝹€(gè)數(shù)據(jù)、數(shù)組、帶返回值的回調(diào)函數(shù))
- 參數(shù)2-觸發(fā)監(jiān)聽的回調(diào)函數(shù),無返回值
- 可選參數(shù)3-對(duì)象
{immediate: true,deep:true},對(duì)象含2個(gè)可選參數(shù)和Vue2參數(shù)效果一致
Vue3的watch和Vue2的watch是基本一樣的
1、需要指定監(jiān)聽數(shù)據(jù)
2、惰性,只在被監(jiān)聽數(shù)據(jù)變化時(shí)才觸發(fā)(immediate屬性可以設(shè)置在初始化的時(shí)候觸發(fā))
監(jiān)聽單個(gè)數(shù)據(jù)
參數(shù)1被監(jiān)聽數(shù)據(jù)的形式:
1、單個(gè)基本數(shù)據(jù)類型;
2、回調(diào)函數(shù):返回值為單個(gè)基本數(shù)據(jù)類型;
// 偵聽一個(gè) getter
//被監(jiān)聽數(shù)據(jù)傳入一個(gè)帶返回值的回調(diào)函數(shù)
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
?
// 直接偵聽一個(gè) ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* ... */
})監(jiān)聽多個(gè)數(shù)據(jù)(傳入數(shù)組)
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* ... */
})官方文檔總結(jié)
以下代碼截取官方文檔,從TS代碼可以看出很多關(guān)于watch和watchEffect函數(shù)參數(shù)和返回值的細(xì)節(jié)!
computed
computed只接收一個(gè)getter函數(shù)
getter觸發(fā)條件:
1、computed返回值首次被讀取時(shí)
2、getter綁定的響應(yīng)式變量被修改時(shí)
computed同時(shí)接收getter函數(shù)對(duì)象和setter函數(shù)對(duì)象
setter觸發(fā)條件:computed返回值被修改時(shí)
// 只讀的
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ù)可傳入一個(gè)onInvalidate函數(shù)作為參數(shù)!
- 可選參數(shù)2-對(duì)象,包含3個(gè)可選屬性flush、onTrack、onTrigger
function watchEffect(
effect: (onInvalidate: InvalidateCbRegistrator) => void,
options?: WatchEffectOptions
): StopHandle
?
interface WatchEffectOptions {
flush?: 'pre' | 'post' | 'sync' // 默認(rèn):'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 = () => voidwatch
- 參數(shù)1-被監(jiān)聽數(shù)據(jù)(形式:?jiǎn)蝹€(gè)數(shù)據(jù)、數(shù)組、帶返回值的回調(diào)函數(shù))
- 參數(shù)2-觸發(fā)監(jiān)聽的回調(diào)函數(shù),無返回值
- 參數(shù)3-傳入
{immediate: true,deep:true}對(duì)象和Vue2參數(shù)效果一致
// 偵聽單一源
function watch<T>(
source: WatcherSource<T>,
callback: (
value: T,
oldValue: T,
onInvalidate: InvalidateCbRegistrator
) => void,
options?: WatchOptions
): StopHandle
?
// 偵聽多個(gè)源
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` 共享選項(xiàng)的類型聲明
interface WatchOptions extends WatchEffectOptions {
immediate?: boolean // 默認(rèn):false
deep?: boolean
}以上就是詳解Vue中Computed與watch的用法與區(qū)別的詳細(xì)內(nèi)容,更多關(guān)于Vue Computed watch的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vuex之this.$store.dispatch()與this.$store.commit()的區(qū)別及說明
這篇文章主要介紹了vuex之this.$store.dispatch()與this.$store.commit()的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
vite項(xiàng)目vite.config.js詳細(xì)配置
vite.config.js是Vite框架中的配置文件,用于配置項(xiàng)目的構(gòu)建和運(yùn)行時(shí)的行為,下面這篇文章主要給大家介紹了關(guān)于vite項(xiàng)目vite.config.js詳細(xì)配置的相關(guān)資料,需要的朋友可以參考下2023-05-05
關(guān)于echarts?清空上一次加載的數(shù)據(jù)問題
這篇文章主要介紹了關(guān)于echarts?清空上一次加載的數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
瀏覽器事件循環(huán)與vue nextTicket的實(shí)現(xiàn)
這篇文章主要介紹了瀏覽器事件循環(huán)(結(jié)合vue nextTicket)的實(shí)現(xiàn)方法,需要的朋友可以參考下2019-04-04

