二維碼
        企資網(wǎng)

        掃一掃關(guān)注

        當(dāng)前位置: 首頁 » 企資快訊 » 匯總 » 正文

        終于徹底搞懂_Watch_WatchEffec

        放大字體  縮小字體 發(fā)布日期:2022-12-12 05:42:21    作者:江造培    瀏覽次數(shù):76
        導(dǎo)讀

        曾經(jīng)以為自己會用 watch 、 watchEffect 了,后來發(fā)現(xiàn)只是略懂皮毛。最近我就把 Vue3 得偵聽器全面梳理了一下,分享給大家??纯从袥]有你不會得吧,一起學(xué)起來!Watch基本用法當(dāng)我們需要在數(shù)據(jù)變化時(shí)執(zhí)行一些“副作

        曾經(jīng)以為自己會用 watch 、 watchEffect 了,后來發(fā)現(xiàn)只是略懂皮毛。最近我就把 Vue3 得偵聽器全面梳理了一下,分享給大家??纯从袥]有你不會得吧,一起學(xué)起來!

        Watch

        基本用法

        當(dāng)我們需要在數(shù)據(jù)變化時(shí)執(zhí)行一些“副作用”:如更改 DOM、執(zhí)行異步操作,我們可以使用 watch 函數(shù):

        <script setup>import { ref, watch } from 'vue'const question = ref('')const answer = ref('This is answer. ;-)')// 偵聽一個(gè) refwatch(question, async (newQuestion, oldQuestion) => { answer.value = 'Thinking...' const res = await fetch('...') answer.value = (await res.json()).answer})</script><template> <input v-model="question" /> <p>{{ answer }}</p></template>

        watch() 一共可以接受三個(gè)參數(shù),偵聽數(shù)據(jù)源、回調(diào)函數(shù)和配置選項(xiàng)。

        偵聽數(shù)據(jù)源

        watch 得第壹個(gè)參數(shù)可以是不同形式得“數(shù)據(jù)源”,它可以是:

      1. 一個(gè) ref
      2. 一個(gè)計(jì)算屬性
      3. 一個(gè) getter 函數(shù)(有返回值得函數(shù))
      4. 一個(gè)響應(yīng)式對象
      5. 以上類型得值組成得數(shù)組

        const x = ref(1)const y = ref(1)const doubleX = computed(() => x.value * 2)const obj = reactive({ count: 0 })// 單個(gè) refwatch(x, (newValue) => { console.log(`x is ${newValue}`)})// 計(jì)算屬性watch(doubleX, (newValue) => { console.log(`doubleX is ${newValue}`)})// getter 函數(shù)watch( () => x.value + y.value, (sum) => { console.log(`sum of x + y is: ${sum}`) })// 響應(yīng)式對象watch(obj, (newValue, oldValue) => { // 在嵌套得屬性變更時(shí)觸發(fā) // 注意:`newValue` 此處和 `oldValue` 是相等得 // 因?yàn)樗鼈兪峭粋€(gè)對象!})// 以上類型得值組成得數(shù)組watch([x, () => y.value], ([newX, newY]) => { console.log(`x is ${newX} and y is ${newY}`)})

        注意,你不能直接偵聽響應(yīng)式對象得屬性值,例如:

        const obj = reactive({ count: 0 })// 錯(cuò)誤,因?yàn)?watch() 得到得參數(shù)是一個(gè) numberwatch(obj.count, (count) => { console.log(`count is: ${count}`)})

        這里需要用一個(gè)返回該屬性得 getter 函數(shù):

        // 提供一個(gè) getter 函數(shù)watch( () => obj.count, (count) => { console.log(`count is: ${count}`) })

        回調(diào)函數(shù)

        watch 得第二個(gè)參數(shù)是數(shù)據(jù)發(fā)生變化時(shí)執(zhí)行得回調(diào)函數(shù)。

        這個(gè)回調(diào)函數(shù)接受三個(gè)參數(shù):新值、舊值,以及一個(gè)用于清理副作用得回調(diào)函數(shù)。該回調(diào)函數(shù)會在副作用下一次執(zhí)行前調(diào)用,可以用來清除無效得副作用,如等待中得異步請求:

        const id = ref(1)const data = ref(null)watch(id, async (newValue, oldValue, onCleanup) => { const { response, cancel } = doAsyncWork(id.value) // `cancel` 會在 `id` 更改時(shí)調(diào)用 // 以便取消之前未完成得請求 onCleanup(cancel) data.value = await response.json()})

        watch 得返回值是一個(gè)用來停止該副作用得函數(shù):

        const unwatch = watch(() => {})// ...當(dāng)該偵聽器不再需要時(shí)unwatch()

        注意:使用同步語句創(chuàng)建得偵聽器,會自動綁定到宿主組件實(shí)例上,并且會在宿主組件卸載時(shí)自動停止。使用異步回調(diào)創(chuàng)建一個(gè)偵聽器,則不會綁定到當(dāng)前組件上,你必須手動停止它,以防內(nèi)存泄漏。如下面這個(gè)例子:

        <script setup>import { watchEffect } from 'vue'// 組件卸載會自動停止watchEffect(() => {})// 組件卸載不會停止!setTimeout(() => { watchEffect(() => {})}, 100)</script>

        配置選項(xiàng)

        watch 得第三個(gè)參數(shù)是一個(gè)可選得對象,支持以下選項(xiàng):

      6. immediate:在偵聽器創(chuàng)建時(shí)立即觸發(fā)回調(diào)。
      7. deep:深度遍歷,以便在深層級變更時(shí)觸發(fā)回調(diào)。
      8. flush:回調(diào)函數(shù)得觸發(fā)時(shí)機(jī)。pre:默認(rèn),dom 更新前調(diào)用,post: dom 更新后調(diào)用,sync 同步調(diào)用。
      9. onTrack / onTrigger:用于調(diào)試得鉤子。在依賴收集和回調(diào)函數(shù)觸發(fā)時(shí)被調(diào)用。

        深層偵聽器

        直接給 watch() 傳入一個(gè)響應(yīng)式對象,會默認(rèn)創(chuàng)建一個(gè)深層偵聽器 —— 所有嵌套得屬性變更時(shí)都會被觸發(fā):

        const obj = reactive({ count: 0 })watch(obj, (newValue, oldValue) => { // 在嵌套得屬性變更時(shí)觸發(fā) // 注意:`newValue` 此處和 `oldValue` 是相等得 // 因?yàn)樗鼈兪峭粋€(gè)對象!})obj.count++

        相比之下,一個(gè)返回響應(yīng)式對象得 getter 函數(shù),只有在對象被替換時(shí)才會觸發(fā):

        const obj = reactive({ someString: 'hello', someObject: { count: 0 }})watch( () => obj.someObject, () => { // 僅當(dāng) obj.someObject 被替換時(shí)觸發(fā) })

        當(dāng)然,你也可以顯式地加上 deep 選項(xiàng),強(qiáng)制轉(zhuǎn)成深層偵聽器:

        watch( () => obj.someObject, (newValue, oldValue) => { // `newValue` 此處和 `oldValue` 是相等得 // 除非 obj.someObject 被整個(gè)替換了 console.log('deep', newValue.count, oldValue.count) }, { deep: true })obj.someObject.count++ // deep 1 1

        深層偵聽一個(gè)響應(yīng)式對象或數(shù)組,新值和舊值是相等得。為了解決這個(gè)問題,我們可以對值進(jìn)行深拷貝。

        watch( () => _.cloneDeep(obj.someObject), (newValue, oldValue) => { // 此時(shí) `newValue` 此處和 `oldValue` 是不相等得 console.log('deep', newValue.count, oldValue.count) }, { deep: true })obj.someObject.count++ // deep 1 0

        注意:深層偵聽需要遍歷所有嵌套得屬性,當(dāng)數(shù)據(jù)結(jié)構(gòu)龐大時(shí),開銷很大。所以我們要謹(jǐn)慎使用,并且留意性能。

        watchEffect

        watch() 是懶執(zhí)行得:當(dāng)數(shù)據(jù)源發(fā)生變化時(shí),才會執(zhí)行回調(diào)。但在某些場景中,我們希望在創(chuàng)建偵聽器時(shí),立即執(zhí)行一遍回調(diào)。當(dāng)然使用 immediate 選項(xiàng)也能實(shí)現(xiàn):

        const url = ref('...')const data = ref(null)async function fetchData() { const response = await fetch(url.value) data.value = await response.json()}// 立即執(zhí)行一次,再偵聽 url 變化watch(url, fetchData, { immediate: true })

        可以看到 watch 用到了三個(gè)參數(shù),我們可以用 watchEffect 來簡化上面得代碼。watchEffect 會立即執(zhí)行一遍回調(diào)函數(shù),如果這時(shí)函數(shù)產(chǎn)生了副作用,Vue 會自動追蹤副作用得依賴關(guān)系,自動分析出偵聽數(shù)據(jù)源。上面得例子可以重寫為:

        const url = ref('...')const data = ref(null)// 一個(gè)參數(shù)就可以搞定watchEffect(async () => { const response = await fetch(url.value) data.value = await response.json()})

        watchEffect 接受兩個(gè)參數(shù),第壹個(gè)參數(shù)是數(shù)據(jù)發(fā)生變化時(shí)執(zhí)行得回調(diào)函數(shù),用法和 watch 一樣。第二個(gè)參數(shù)是一個(gè)可選得對象,支持 flush 和 onTrack / onTrigger 選項(xiàng),功能和 watch 相同。

        注意:watchEffect 僅會在其同步執(zhí)行期間,才追蹤依賴。使用異步回調(diào)時(shí),只有在第壹個(gè) await 之前訪問到得依賴才會被追蹤。

        watch vs. watchEffect

        watch 和 watchEffect 得主要功能是相同得,都能響應(yīng)式地執(zhí)行回調(diào)函數(shù)。它們得區(qū)別是追蹤響應(yīng)式依賴得方式不同:

      10. watch 只追蹤明確定義得數(shù)據(jù)源,不會追蹤在回調(diào)中訪問到得東西;默認(rèn)情況下,只有在數(shù)據(jù)源發(fā)生改變時(shí)才會觸發(fā)回調(diào);watch 可以訪問偵聽數(shù)據(jù)得新值和舊值。
      11. watchEffect 會初始化執(zhí)行一次,在副作用發(fā)生期間追蹤依賴,自動分析出偵聽數(shù)據(jù)源;watchEffect 無法訪問偵聽數(shù)據(jù)得新值和舊值。

        簡單一句話,watch 功能更加強(qiáng)大,而 watchEffect 在某些場景下更加簡潔。

        好得,今天得分享就到這里。不知道你是不是徹底搞懂 watch 、 watchEffect 了呢,歡迎在評論區(qū)留言!

        如果覺得有用,記得點(diǎn)贊支持一哈 ~

      12.  
        (文/江造培)
        免責(zé)聲明
        本文僅代表作發(fā)布者:江造培個(gè)人觀點(diǎn),本站未對其內(nèi)容進(jìn)行核實(shí),請讀者僅做參考,如若文中涉及有違公德、觸犯法律的內(nèi)容,一經(jīng)發(fā)現(xiàn),立即刪除,需自行承擔(dān)相應(yīng)責(zé)任。涉及到版權(quán)或其他問題,請及時(shí)聯(lián)系我們刪除處理郵件:weilaitui@qq.com。
         

        Copyright ? 2016 - 2025 - 企資網(wǎng) 48903.COM All Rights Reserved 粵公網(wǎng)安備 44030702000589號

        粵ICP備16078936號

        微信

        關(guān)注
        微信

        微信二維碼

        WAP二維碼

        客服

        聯(lián)系
        客服

        聯(lián)系客服:

        在線QQ: 303377504

        客服電話: 020-82301567

        E_mail郵箱: weilaitui@qq.com

        微信公眾號: weishitui

        客服001 客服002 客服003

        工作時(shí)間:

        周一至周五: 09:00 - 18:00

        反饋

        用戶
        反饋

        主站蜘蛛池模板: 国产av熟女一区二区三区| 精品视频一区在线观看| 国产人妖视频一区二区| 亚洲AV无码国产精品永久一区| 一区五十路在线中出| 亚洲一区欧洲一区| 久久一区二区三区免费播放| 加勒比精品久久一区二区三区| 中文字幕在线视频一区| 国产免费一区二区三区VR| 亚洲国产欧美日韩精品一区二区三区| 熟女少妇丰满一区二区| 一区二区精品久久| 国产微拍精品一区二区| 国产成人精品久久一区二区三区| 中文字幕一区二区区免| 高清一区二区三区| 日本一区二区三区在线观看视频| 精品一区二区三区在线观看视频 | 无码人妻精品一区二区蜜桃网站| 久久精品国产一区二区三区不卡| 日本精品一区二区在线播放| 亚洲AV无码国产一区二区三区| 亚洲一区二区电影| 无码国产伦一区二区三区视频 | 国精无码欧精品亚洲一区| 搜日本一区二区三区免费高清视频| 国产一区二区草草影院| 亚洲性色精品一区二区在线| 日韩好片一区二区在线看| 日本不卡在线一区二区三区视频| 精品国产一区二区三区AV性色| 国产av福利一区二区三巨| 视频一区视频二区日韩专区| 国产一区二区精品在线观看| 精品视频午夜一区二区| 一区二区三区四区精品| 久久久久人妻一区精品| 99精品国产一区二区三区| 亚洲色婷婷一区二区三区| 精品一区二区三区在线视频|