最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3中watch和watchEffect的區(qū)別及使用技巧總結(jié)

 更新時間:2026年02月27日 09:16:18   作者:涔溪  
在Vue.js里,watch和watchEffect都用于響應(yīng)式地追蹤數(shù)據(jù)變化并執(zhí)行相應(yīng)操作,不過它們在使用方式、應(yīng)用場景等方面存在差異,這篇文章主要介紹了Vue3中watch和watchEffect區(qū)別及使用技巧的相關(guān)資料,需要的朋友可以參考下

詳細(xì)講解Vue 3 組合式 API 中watchwatchEffect的核心區(qū)別,以及它們的實際使用技巧,以便在開發(fā)中根據(jù)場景正確選擇合適的偵聽器。

一、先明確兩者的核心定位

在 Vue 3 組合式 API 中,watchwatchEffect都是用于監(jiān)聽響應(yīng)式數(shù)據(jù)變化并執(zhí)行副作用的工具,但設(shè)計理念和使用場景有明顯區(qū)別:

  • watch顯式監(jiān)聽指定的響應(yīng)式數(shù)據(jù)源,惰性執(zhí)行(默認(rèn)),支持訪問新舊值,控制力更強。
  • watchEffect隱式監(jiān)聽函數(shù)內(nèi)用到的所有響應(yīng)式數(shù)據(jù)源,立即執(zhí)行(默認(rèn)),自動追蹤依賴,寫法更簡潔。

二、核心區(qū)別對比(表格 + 示例)

對比維度watchwatchEffect
依賴追蹤方式顯式指定監(jiān)聽源(需明確告訴要監(jiān)聽什么)隱式追蹤(自動收集函數(shù)內(nèi)用到的響應(yīng)式數(shù)據(jù))
執(zhí)行時機默認(rèn)懶執(zhí)行(僅當(dāng)監(jiān)聽源變化時執(zhí)行)默認(rèn)立即執(zhí)行(組件掛載時先執(zhí)行一次,再監(jiān)聽變化)
新舊值訪問支持(回調(diào)函數(shù)接收新值、舊值參數(shù))不支持(只能訪問當(dāng)前最新值)
監(jiān)聽源類型可監(jiān)聽單個值、多個值、對象屬性、計算屬性等只能監(jiān)聽函數(shù)內(nèi)直接使用的響應(yīng)式數(shù)據(jù)
停止監(jiān)聽返回停止函數(shù),或依賴組件卸載自動停止同左(返回停止函數(shù),組件卸載自動停止)
清除副作用需通過onInvalidate回調(diào)(Vue 3.2 + 推薦)同左(回調(diào)函數(shù)接收onInvalidate參數(shù))

1. 依賴追蹤方式對比(最核心區(qū)別)

watch:顯式指定監(jiān)聽源

必須明確告訴watch要監(jiān)聽哪個 / 哪些響應(yīng)式數(shù)據(jù),未指定的不會被追蹤:

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)
const name = ref('Vue')

// 顯式監(jiān)聽 count,name 變化不會觸發(fā)此 watch
watch(count, (newVal, oldVal) => {
  console.log(`count從${oldVal}變成${newVal}`)
})

// 顯式監(jiān)聽多個源(數(shù)組形式)
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
  console.log(`count變化:${oldCount}→${newCount},name變化:${oldName}→${newName}`)
})
</script>

watchEffect:隱式追蹤依賴

無需指定監(jiān)聽源,函數(shù)內(nèi)用到的所有響應(yīng)式數(shù)據(jù)都會被自動追蹤:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)
const name = ref('Vue')

// 自動追蹤 count 和 name(函數(shù)內(nèi)用到了這兩個響應(yīng)式數(shù)據(jù))
watchEffect(() => {
  console.log(`當(dāng)前count:${count.value},當(dāng)前name:${name.value}`)
})
// 首次執(zhí)行輸出:當(dāng)前count:0,當(dāng)前name:Vue(立即執(zhí)行特性)
// 當(dāng)count或name變化時,會重新執(zhí)行
</script>

2. 執(zhí)行時機對比

watch:默認(rèn)懶執(zhí)行

只有監(jiān)聽源發(fā)生變化時才會執(zhí)行,組件掛載時不會主動執(zhí)行:

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)

// 組件掛載時不會執(zhí)行,只有 count 變化時才執(zhí)行
watch(count, (newVal) => {
  console.log(`count變化了:${newVal}`)
})

// 若需要立即執(zhí)行,需手動設(shè)置 immediate: true
watch(count, (newVal) => {
  console.log(`count(立即執(zhí)行):${newVal}`)
}, { immediate: true }) // 組件掛載時執(zhí)行一次,之后 count 變化再執(zhí)行
</script>

watchEffect:默認(rèn)立即執(zhí)行

組件掛載時會先執(zhí)行一次(用于收集依賴),之后依賴變化時再執(zhí)行:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)

// 組件掛載時立即執(zhí)行一次,之后 count 變化時再執(zhí)行
watchEffect(() => {
  console.log(`count:${count.value}`)
})
// 輸出:count:0(掛載時)→ count:1(當(dāng)count++時)
</script>

3. 新舊值訪問對比

watch:支持訪問新舊值

回調(diào)函數(shù)的第一個參數(shù)是新值,第二個參數(shù)是舊值(引用類型需注意淺對比):

<script setup>
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newVal, oldVal) => {
  console.log(`舊值:${oldVal},新值:${newVal}`) // 例如:舊值:0,新值:1
})

// 監(jiān)聽對象(需注意:默認(rèn)是淺監(jiān)聽,對象內(nèi)部屬性變化需開啟 deep: true)
const user = ref({ name: 'Vue', age: 3 })
watch(user, (newUser, oldUser) => {
  console.log('user變化了', newUser, oldUser)
}, { deep: true }) // 深度監(jiān)聽對象內(nèi)部屬性
</script>

watchEffect:不支持訪問舊值

只能訪問當(dāng)前最新的響應(yīng)式數(shù)據(jù),無法獲取變化前的值:

<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)

watchEffect(() => {
  // 只能拿到當(dāng)前值,拿不到變化前的舊值
  console.log(`當(dāng)前count:${count.value}`)
})
</script>

三、使用技巧與場景選擇

1. 什么時候用watch?

  • 需要訪問新舊值時(如對比變化前后的數(shù)據(jù));
  • 需要明確控制監(jiān)聽源(只監(jiān)聽特定數(shù)據(jù),避免無關(guān)依賴觸發(fā));
  • 需要延遲執(zhí)行(如使用 flush: 'post' 在 DOM 更新后執(zhí)行);
  • 需要深度監(jiān)聽對象 / 數(shù)組且需要精細(xì)控制時;
  • 需要懶執(zhí)行(僅在數(shù)據(jù)變化時執(zhí)行,避免初始化開銷)。

實用技巧:

  • 監(jiān)聽對象單個屬性:用函數(shù)返回具體屬性(避免深度監(jiān)聽整個對象,提升性能):

    <script setup>
    import { ref, watch } from 'vue'
    
    const user = ref({ name: 'Vue', age: 3 })
    
    // 只監(jiān)聽 user.name,無需深度監(jiān)聽整個對象
    watch(() => user.value.name, (newName) => {
      console.log(`用戶名變化:${newName}`)
    })
    </script>
    
  • 延遲執(zhí)行(DOM 更新后):使用flush: 'post'

    watch(count, () => {
      // 此時DOM已經(jīng)更新,可以獲取更新后的DOM元素
      console.log(document.getElementById('count').innerText)
    }, { flush: 'post' })
    

2. 什么時候用watchEffect?

  • 副作用依賴多個響應(yīng)式數(shù)據(jù),且無需區(qū)分哪個變化(自動追蹤所有用到的);
  • 需要立即執(zhí)行副作用(如初始化時請求數(shù)據(jù),之后依賴變化重新請求);
  • 不需要訪問舊值,只關(guān)注當(dāng)前最新狀態(tài);
  • 寫法簡潔優(yōu)先(減少代碼量)。

實用技巧:

  • 清除副作用(如取消請求、清除定時器):使用onInvalidate 回調(diào)(組件卸載或副作用重新執(zhí)行前觸發(fā)):

    <script setup>
    import { ref, watchEffect } from 'vue'
    import axios from 'axios'
    
    const id = ref(1)
    
    watchEffect((onInvalidate) => {
      // 發(fā)起請求
      const request = axios.get(`/api/data/${id.value}`)
      
      // 清除函數(shù):組件卸載或 id 變化時觸發(fā)
      onInvalidate(() => {
        request.cancel() // 取消請求
      })
    })
    </script>
    
  • 延遲執(zhí)行(同 watch):使用flush: 'post'

    watchEffect(() => {
      // DOM更新后執(zhí)行
      console.log(document.getElementById('count').innerText)
    }, { flush: 'post' })
    

3. 共同技巧:停止監(jiān)聽

watchwatchEffect都返回一個停止函數(shù),調(diào)用后會停止監(jiān)聽(組件卸載時會自動停止,無需手動調(diào)用):

<script setup>
import { ref, watch, watchEffect } from 'vue'

const count = ref(0)

// watch 停止監(jiān)聽
const stopWatch = watch(count, (newVal) => {
  console.log(`count:${newVal}`)
})

// watchEffect 停止監(jiān)聽
const stopWatchEffect = watchEffect(() => {
  console.log(`count:${count.value}`)
})

// 手動停止監(jiān)聽(如某個條件滿足時)
const stopAll = () => {
  stopWatch()
  stopWatchEffect()
}
</script>

總結(jié)

核心區(qū)別

  1. 依賴追蹤watch顯式指定源,watchEffect隱式追蹤;
  2. 執(zhí)行時機watch默認(rèn)懶執(zhí)行,watchEffect默認(rèn)立即執(zhí)行;
  3. 新舊值watch支持訪問新舊值,watchEffect不支持。

場景選擇

  • 需舊值、明確監(jiān)聽源、精細(xì)控制 → 用 watch;
  • 多依賴、立即執(zhí)行、簡潔優(yōu)先 → 用 watchEffect。

關(guān)鍵技巧

  1. watch監(jiān)聽對象單個屬性時,用函數(shù)返回(避免深度監(jiān)聽);
  2. watchEffect需清除副作用時,使用 onInvalidate;
  3. 兩者都可通過返回的停止函數(shù)手動停止監(jiān)聽,組件卸載時自動停止。

到此這篇關(guān)于Vue3中watch和watchEffect的區(qū)別及使用技巧總結(jié)的文章就介紹到這了,更多相關(guān)Vue3 watch和watchEffect使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue使用advanced-mark.js實現(xiàn)高亮文字效果

    vue使用advanced-mark.js實現(xiàn)高亮文字效果

    在日常項目中我們往往會有搜索高亮的需求,下面這篇文章主要介紹了vue使用advanced-mark.js實現(xiàn)高亮文字效果的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-08-08
  • vue中如何實現(xiàn)pdf文件預(yù)覽的方法

    vue中如何實現(xiàn)pdf文件預(yù)覽的方法

    這篇文章主要介紹了vue中如何實現(xiàn)pdf文件預(yù)覽的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • vue.js body的css不生效問題及解決

    vue.js body的css不生效問題及解決

    這篇文章主要介紹了vue.js body的css不生效問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Vue?Echarts實現(xiàn)帶滾動效果的柱形圖

    Vue?Echarts實現(xiàn)帶滾動效果的柱形圖

    這篇文章主要為大家詳細(xì)介紹了Vue?Echarts實現(xiàn)帶滾動效果的柱形圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • vue引入微信sdk 實現(xiàn)分享朋友圈獲取地理位置功能

    vue引入微信sdk 實現(xiàn)分享朋友圈獲取地理位置功能

    這篇文章主要介紹了h5 vue引入微信sdk 實現(xiàn)分享朋友圈,分享給朋友,獲取地理位置功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-07-07
  • Vue中forEach()的使用方法例子

    Vue中forEach()的使用方法例子

    這篇文章主要給大家介紹了關(guān)于Vue中forEach()使用方法的相關(guān)資料,forEach和map是數(shù)組的兩個方法,作用都是遍歷數(shù)組,在vue項目的處理數(shù)據(jù)中經(jīng)常會用到,需要的朋友可以參考下
    2023-09-09
  • Vue如何將頁面導(dǎo)出成PDF文件

    Vue如何將頁面導(dǎo)出成PDF文件

    這篇文章主要為大家詳細(xì)介紹了Vue如何將頁面導(dǎo)出成PDF文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • 一篇文章告訴你如何編寫Vue插件

    一篇文章告訴你如何編寫Vue插件

    這篇文章主要為大家介紹了如何編寫Vue插件,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • Vue開發(fā)指南之重點知識梳理

    Vue開發(fā)指南之重點知識梳理

    這篇文章主要介紹了Vue開發(fā)指南之重點知識梳理,對Vue框架感興趣的同學(xué),可以參考下
    2021-05-05
  • vue計算屬性無法監(jiān)聽到數(shù)組內(nèi)部變化的解決方案

    vue計算屬性無法監(jiān)聽到數(shù)組內(nèi)部變化的解決方案

    今天小編就為大家分享一篇vue計算屬性無法監(jiān)聽到數(shù)組內(nèi)部變化的解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11

最新評論

唐河县| 旅游| 西吉县| 新绛县| 文昌市| 兰溪市| 五家渠市| 鄯善县| 藁城市| 铜梁县| 丽水市| 义乌市| 临夏市| 施甸县| 广宗县| 浦北县| 濮阳市| 砚山县| 玉田县| 壤塘县| 龙南县| 荔波县| 蒙阴县| 南昌县| 遵化市| 临泉县| 板桥市| 南溪县| 金寨县| 昆山市| 平阴县| 深圳市| 桂林市| 时尚| 卢氏县| 南昌市| 鸡东县| 晋中市| 阿拉尔市| 宁安市| 运城市|