Vue3中Watch、Watcheffect、Computed的使用和區(qū)別解析
Vue3–Watch、Watcheffect、Computed的使用和區(qū)別
一、watch
1.功能
watch
用于監(jiān)聽響應(yīng)式數(shù)據(jù)的變化,并在數(shù)據(jù)變化時執(zhí)行特定的回調(diào)函數(shù)。適合在響應(yīng)式數(shù)據(jù)變化時執(zhí)行異步操作或復(fù)雜邏輯。
2.主要特點
- 指定數(shù)據(jù)監(jiān)聽:可以精確地監(jiān)聽一個或多個響應(yīng)式數(shù)據(jù)。
- 回調(diào)函數(shù):數(shù)據(jù)變化時調(diào)用指定的回調(diào)函數(shù),并傳入新值和舊值。
- 配置項:支持
immediate
(是否立即執(zhí)行回調(diào))和deep
(是否深度監(jiān)聽)配置。
3.典型應(yīng)用場景
- 需要執(zhí)行異步操作(如 API 請求)。
- 需要執(zhí)行復(fù)雜的副作用操作。
- 需要監(jiān)聽深層次的對象變化。
import { ref, watch } from 'vue'; const count = ref(0); watch(count, (newValue, oldValue) => { console.log(`依賴值改變${oldValue} -- ${newValue}`); }, { immediate: true, deep: false });
4.參數(shù)介紹
- 第一個參數(shù):需要監(jiān)聽的響應(yīng)式數(shù)據(jù)或 getter 函數(shù)。
- 第二個參數(shù):回調(diào)函數(shù),接受新值和舊值作為參數(shù)。
- 第三個參數(shù)(可選):配置項,包括
immediate
和deep
。
5.基本使用示例(父子組件結(jié)合ElementUI)
父組件
<template> <div> <!-- 使用 ElementUI 的 el-input 組件輸入內(nèi)容 --> <el-input v-model="parentInput" placeholder="Enter something"></el-input> <!-- 將輸入內(nèi)容傳遞給子組件 --> <ChildComponent :inputValue="parentInput" /> </div> </template> <script setup> import { ref } from 'vue'; import ChildComponent from './ChildComponent.vue'; // 創(chuàng)建一個響應(yīng)式變量 parentInput,用于存儲輸入內(nèi)容 const parentInput = ref(''); </script>
子組件
<template> <div> <!-- 顯示父組件傳遞的輸入內(nèi)容 --> <p>父組件輸入: {{ inputValue }}</p> </div> </template> <script setup> import { watch, toRefs } from 'vue'; // 定義 props 接收父組件傳遞的數(shù)據(jù) const props = defineProps({ inputValue: String, }); // 解構(gòu) props const { inputValue } = toRefs(props); // 監(jiān)聽 inputValue 的變化,并在變化時執(zhí)行回調(diào) watch(inputValue, (newValue) => { console.log(`父組件輸入改變: ${newValue}`); }); </script>
6.常見用法
1. 監(jiān)聽單個響應(yīng)式數(shù)據(jù)
import { ref, watch } from 'vue'; const count = ref(0); watch(count, (newValue, oldValue) => { console.log(`count值改變 ${oldValue} -- ${newValue}`); });
2. 監(jiān)聽多個響應(yīng)式數(shù)據(jù)
import { ref, watch } from 'vue'; const count1 = ref(0); const count2 = ref(0); watch([count1, count2], ([newCount1, newCount2], [oldCount1, oldCount2]) => { console.log(`count1值改變 ${oldCount1} -- ${newCount1}`); console.log(`count2值改變 ${oldCount2} -- ${newCount2}`); });
3. 深度監(jiān)聽對象{ deep: true }
import { ref, watch } from 'vue'; const person = ref({ name: 'John', age: 30 }); watch(person, (newPerson, oldPerson) => { console.log(`Person改變 ${oldPerson.name} -- ${newPerson.name}`); }, { deep: true });
4. 立即執(zhí)行回調(diào){ immediate: true }
import { ref, watch } from 'vue'; const count = ref(0); watch(count, (newValue, oldValue) => { console.log(`count值改變 ${oldValue} -- ${newValue}`); }, { immediate: true });
5. 監(jiān)聽 getter 函數(shù)
import { ref, watch } from 'vue'; const count = ref(0); // 使用 watch 監(jiān)聽一個 getter 函數(shù) watch( // 第一個參數(shù)是一個 getter 函數(shù),該函數(shù)返回我們要監(jiān)聽的計算值 () => count.value + 1, // 第二個參數(shù)是回調(diào)函數(shù),當(dāng) getter 函數(shù)的返回值發(fā)生變化時,該回調(diào)函數(shù)會被調(diào)用 (newValue, oldValue) => { // 打印舊值和新值 console.log(`Computed值改變 ${oldValue} -- ${newValue}`); } );
二、watchEffect
1.功能
watchEffect
用于自動運行一個副作用函數(shù),并追蹤其依賴。任何依賴變化時都會重新運行該函數(shù)。適合用來執(zhí)行副作用,但不需要明確指定依賴。
2.主要特點
- 自動依賴追蹤:自動追蹤副作用函數(shù)中的響應(yīng)式數(shù)據(jù)依賴。
- 立即執(zhí)行:函數(shù)會立即執(zhí)行一次,并在依賴變化時重新執(zhí)行。
- 簡潔性:不需要手動指定依賴,代碼更簡潔。
3.典型應(yīng)用場景
- 需要自動運行副作用函數(shù),并自動管理依賴。
- 界面更新或 DOM 操作。
import { ref, watchEffect } from 'vue'; const count = ref(0); watchEffect(() => { console.log(`count: ${count.value}`); }, { flush: 'pre' });
4.參數(shù)介紹
- 第一個參數(shù):副作用函數(shù)。
- 第二個參數(shù)(可選):配置項,包括
flush
。
watchEffect
的 flush
選項用于控制副作用函數(shù)的觸發(fā)時機。flush
選項有三種可能的值:
pre
:在組件更新前觸發(fā)(這是默認(rèn)值)。post
:在組件更新后觸發(fā)。sync
:同步地觸發(fā)。
flush: ‘pre’
默認(rèn)情況下,watchEffect
會在組件更新之前運行副作用函數(shù)。這意味著當(dāng)響應(yīng)式數(shù)據(jù)變化時,副作用會在 DOM 更新前執(zhí)行。
flush: ‘post’
將 flush
設(shè)置為 'post'
可以在組件更新后觸發(fā)副作用函數(shù)。這對于那些需要訪問更新后的 DOM 元素的副作用來說很有用。
flush: ‘sync’
將 flush
設(shè)置為 'sync'
可以使副作用同步觸發(fā),而不是等到下一個微任務(wù)隊列。這意味著副作用會立即在響應(yīng)式數(shù)據(jù)變化時執(zhí)行。
import { ref, watchEffect } from 'vue'; const count = ref(0); // 默認(rèn) flush: 'pre' watchEffect(() => { console.log(`count (pre): ${count.value}`); }); // flush: 'post' watchEffect(() => { console.log(`count (post): ${count.value}`); }, { flush: 'post' }); // flush: 'sync' watchEffect(() => { console.log(`count (sync): ${count.value}`); }, { flush: 'sync' }); count.value++;
三個 watchEffect
會在不同的時機記錄 count
的值:
flush: 'pre'
會在 DOM 更新前執(zhí)行。flush: 'post'
會在 DOM 更新后執(zhí)行。flush: 'sync'
會同步執(zhí)行。
5.基本使用示例(父子組件結(jié)合ElementUI)
父組件
<template> <div> <!-- 使用 ElementUI 的 el-slider 組件輸入數(shù)值 --> <el-slider v-model="sliderValue"></el-slider> <!-- 將滑動條的值傳遞給子組件 --> <ChildComponent :sliderValue="sliderValue" /> </div> </template> <script setup> import { ref } from 'vue'; import ChildComponent from './ChildComponent.vue'; // 創(chuàng)建一個響應(yīng)式變量 sliderValue,用于存儲滑動條的值 const sliderValue = ref(50); </script>
子組件
<template> <div> <!-- 顯示父組件傳遞的滑動條的值 --> <p>Slider value: {{ sliderValue }}</p> </div> </template> <script setup> import { watchEffect, toRefs } from 'vue'; // 定義 props 接收父組件傳遞的數(shù)據(jù) const props = defineProps({ sliderValue: Number, }); // 解構(gòu) props const { sliderValue } = toRefs(props); // 監(jiān)聽 sliderValue 的變化,并在變化時執(zhí)行副作用函數(shù) watchEffect(() => { console.log(`Slider: ${sliderValue.value}`); }); </script>
6.常見用法
1. 基本用法
import { ref, watchEffect } from 'vue'; const count = ref(0); watchEffect(() => { console.log(`count: ${count.value}`); });
2. 取消副作用
import { ref, watchEffect } from 'vue'; const count = ref(0); const stop = watchEffect(() => { console.log(`count: ${count.value}`); }); // 停止副作用 stop();
3. 延遲執(zhí)行{ flush: ‘post’ }
import { ref, watchEffect } from 'vue'; const count = ref(0); watchEffect(() => { console.log(`count: ${count.value}`); }, { flush: 'post' });
4. 自定義調(diào)度
import { ref, watchEffect } from 'vue'; const count = ref(0); // 使用 watchEffect 自動追蹤副作用 watchEffect( () => { // 這個函數(shù)在 count 發(fā)生變化時會被調(diào)用 console.log(`count: ${count.value}`); }, { // 配置項:onTrack 和 onTrigger 是調(diào)試鉤子 // onTrack 會在副作用追蹤依賴時調(diào)用 onTrack(e) { console.log('tracked', e); }, // onTrigger 會在依賴變化導(dǎo)致副作用重新執(zhí)行時調(diào)用 onTrigger(e) { console.log('triggered', e); } } );
三、computed
1.功能
computed
用于聲明計算屬性,計算屬性會根據(jù)其依賴的響應(yīng)式數(shù)據(jù)自動更新,并且具有緩存特性。適合計算派生狀態(tài)或數(shù)據(jù)。
2.主要特點
- 依賴管理:計算屬性根據(jù)依賴的響應(yīng)式數(shù)據(jù)自動更新。
- 緩存:只有當(dāng)依賴的數(shù)據(jù)變化時,計算屬性才會重新計算。
- 簡潔性:聲明式地定義派生數(shù)據(jù),代碼簡潔且易于維護。
3.典型應(yīng)用場景
- 需要根據(jù)其他響應(yīng)式數(shù)據(jù)派生出新的數(shù)據(jù)。
- 需要高效的、緩存的計算屬性。
import { ref, computed } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2);
4.參數(shù)介紹
- 第一個參數(shù):getter 函數(shù),返回計算屬性的值。
- 第二個參數(shù)(可選):setter 函數(shù),用于設(shè)置計算屬性的值(可寫計算屬性)。
5.基本使用示例(父子組件結(jié)合ElementUI)
父組件
<template> <div> <!-- 使用 ElementUI 的 el-input 組件輸入數(shù)值 --> <el-input v-model="inputValue" placeholder="Enter a number"></el-input> <!-- 將輸入的數(shù)值傳遞給子組件 --> <ChildComponent :number="inputValue" /> </div> </template> <script setup> import { ref } from 'vue'; import ChildComponent from './ChildComponent.vue'; // 創(chuàng)建一個響應(yīng)式變量 inputValue,用于存儲輸入的數(shù)值 const inputValue = ref(0); </script>
子組件
<template> <div> <!-- 顯示父組件傳遞的數(shù)值的平方 --> <p>Squared value: {{ squaredNumber }}</p> </div> </template> <script setup> import { computed, toRefs } from 'vue'; // 定義 props 接收父組件傳遞的數(shù)據(jù) const props = defineProps({ number: Number, }); // 解構(gòu) props const { number } = toRefs(props); // 創(chuàng)建一個計算屬性 squaredNumber,計算 number 的平方 const squaredNumber = computed(() => number.value * number.value); </script>
6.常見用法
1. 基本用法
import { ref, computed } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2);
2. 可寫計算屬性 (get set)
import { ref, computed } from 'vue'; const firstName = ref('John'); const lastName = ref('Doe'); const fullName = computed({ get: () => `${firstName.value} ${lastName.value}`, set: (newValue) => { const names = newValue.split(' '); firstName.value = names[0]; lastName.value = names[1]; }, });
3. 依賴其他計算屬性
import { ref, computed } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2); const tripleCount = computed(() => doubleCount.value * 1.5);
4. 使用在模板中
<template> <div>{{ doubleCount }}</div> </template> <script setup> import { ref, computed } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2); </script>
5. 配合 watch 使用
import { ref, computed, watch } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2); watch(doubleCount, (newValue) => { console.log(`doubleCount: ${newValue}`); });
6. 配合 watchEffect 使用
import { ref, computed, watchEffect } from 'vue'; const count = ref(0); const doubleCount = computed(() => count.value * 2); watchEffect(() => { console.log(`doubleCount: ${doubleCount.value}`); });
四、總結(jié)與區(qū)別
watch
的多種用法
- 監(jiān)聽單個響應(yīng)式數(shù)據(jù)。
- 監(jiān)聽多個響應(yīng)式數(shù)據(jù)。
- 深度監(jiān)聽對象。{ deep: true }
- 立即執(zhí)行回調(diào)。{ immediate: true }
- 監(jiān)聽 getter 函數(shù)。
watchEffect
的多種用法
- 基本用法。
- 取消副作用。
- 延遲執(zhí)行。{ flush: ‘post’ }
- 自定義調(diào)度。
computed
的多種用法
- 基本用法。
- 可寫計算屬性。 (get set)依賴其他計算屬性。使
- 用在模板中。
- 配合
watch
使用。 - 配合
watchEffect
使用。
區(qū)別
特性 | watch | watchEffect | computed |
---|---|---|---|
功能 | 監(jiān)聽響應(yīng)式數(shù)據(jù)變化并執(zhí)行回調(diào) | 自動運行副作用函數(shù)并追蹤依賴 | 聲明計算屬性,根據(jù)依賴自動更新并緩存 |
依賴管理 | 手動指定 | 自動追蹤 | 自動管理 |
緩存 | 無 | 無 | 有 |
適用場景 | 異步操作、復(fù)雜副作用、深度監(jiān)聽 | 界面更新、副作用函數(shù) | 派生狀態(tài)、數(shù)據(jù)計算 |
優(yōu)點 | 精確控制、支持異步操作 | 自動依賴追蹤、代碼簡潔 | 聲明式、自動更新、緩存 |
缺點 | 需要手動指定依賴、代碼相對復(fù)雜 | 每次依賴變化時都會重新執(zhí)行副作用函數(shù) | 需要在創(chuàng)建時指定依賴,無法動態(tài)改變計算邏輯 |
Watch、Watcheffect、Computed三種方法各有優(yōu)劣,選擇使用哪種方法主要取決于具體的應(yīng)用場景和需求。watch
適合復(fù)雜的副作用操作,watchEffect
適合簡單的自動副作用管理,而 computed
適合聲明式的派生狀態(tài)計算。
到此這篇關(guān)于Vue3中Watch、Watcheffect、Computed的使用和區(qū)別解析的文章就介紹到這了,更多相關(guān)Vue3--Watch、Watcheffect、Computed內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解
這篇文章主要為大家介紹了vue2從數(shù)據(jù)變化到視圖變化之nextTick使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09vue獲取當(dāng)前日期時間(使用moment和new?Date())
在項目開發(fā)中我遇到了日期范圍選擇器,兩種獲取當(dāng)前日期并做處理的寫法,這里記錄一下,下面這篇文章主要給大家介紹了關(guān)于vue獲取當(dāng)前日期時間(使用moment和new?Date())的相關(guān)資料,需要的朋友可以參考下2023-06-06Vue3.0監(jiān)聽器watch與watchEffect詳解
在 Vue 3 中,watch 仍然是一種用于監(jiān)聽數(shù)據(jù)變化并執(zhí)行相應(yīng)操作的方式,不過在組合式 API 中,watch 的使用方式與選項式 API 略有不同,這篇文章主要介紹了Vue3.0監(jiān)聽器watch與watchEffect,需要的朋友可以參考下2023-12-12詳解vue beforeRouteEnter 異步獲取數(shù)據(jù)給實例問題
這篇文章主要介紹了vue beforeRouteEnter 異步獲取數(shù)據(jù)給實例問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08Vue?中ref()和?reactive()響應(yīng)式數(shù)據(jù)的使用方法
article介紹Vue3中ref()和reactive()函數(shù)的使用方法,ref()用于創(chuàng)建基本數(shù)據(jù)類型的響應(yīng)式引用,reactive()用于創(chuàng)建響應(yīng)式對象,本文介紹Vue中ref()和reactive()響應(yīng)式數(shù)據(jù)的使用方法,感興趣的朋友一起看看吧2025-01-01