<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Vue3 筆記

      Vue3 筆記

      關于ref 和 reactive

      • ref是一個創建響應式的API,它可以將普通的 JavaScript數據(基本類型和復雜類型) 變為響應式數據。ref函數接受一個初始值作為參數,并返回一個響應式的引用對象。
      • reactive是一個用于創建響應式對象的API。它接受一個普通的 JavaScript對象(復雜類型) 作為參數,并返回一個響應式的代理

      reactive底層是通過Proxy來實現數據劫持的,創建代理對象,可操作的數據必須是對象,不能是原始類型

      ref通過對原始類型包裹在一個帶有.value屬性的特殊對象中,再使用 Proxy劫持該對象,并返回代理對象。非原始類型傳遞給ref,將通過reactive轉換為響應式代理對象。

      reactive的局限性

      1. 有限的值類型:它只能用于對象類型 (對象、數組和如 MapSet 這樣的集合類型)。它不能持有如 stringnumberboolean 這樣的原始類型
      2. 不能替換整個對象:由于 Vue 的響應式跟蹤是通過屬性訪問實現的,因此我們必須始終保持對響應式對象的相同引用。這意味著我們不能輕易地“替換”響應式對象,因為這樣的話與第一個引用的響應性連接將丟失:
      let state = reactive({ count: 0 })
      
      // 上面的 ({ count: 0 }) 引用將不再被追蹤
      // (響應性連接已丟失!)
      state = reactive({ count: 1 })
      

      監聽器

      監聽器,能在狀態變化時執行一些“副作用”:例如更改 DOM,或是根據異步操作的結果去修改另一處的狀態。

      watch

      在組合式 API 中,我們可以使用 watch 函數在每次響應式狀態發生變化時觸發回調函數:

      <script setup>
      import { ref, watch } from 'vue'
      
      const question = ref('')
      const answer = ref('Questions usually contain a question mark. ;-)')
      const loading = ref(false)
      
      // 可以直接偵聽一個 ref
      watch(question, async (newQuestion, oldQuestion) => {
        if (newQuestion.includes('?')) {
          loading.value = true
          answer.value = 'Thinking...'
          try {
            const res = await fetch('https://yesno.wtf/api')
            answer.value = (await res.json()).answer
          } catch (error) {
            answer.value = 'Error! Could not reach the API. ' + error
          } finally {
            loading.value = false
          }
        }
      })
      </script>
      
      <template>
        <p>
          Ask a yes/no question:
          <input v-model="question" :disabled="loading" />
        </p>
        <p>{{ answer }}</p>
      </template>
      

      偵聽數據源類型

      watch 的第一個參數可以是不同形式的“數據源”:它可以是一個 ref (包括計算屬性)、一個響應式對象、一個getter函數 、或多個數據源組成的數組

      const x = ref(0)
      const y = ref(0)
      
      // 單個 ref
      watch(x, (newX) => {
        console.log(`x is ${newX}`)
      })
      
      // getter 函數
      watch(
        () => x.value + y.value,
        (sum) => {
          console.log(`sum of x + y is: ${sum}`)
        }
      )
      
      // 多個來源組成的數組
      watch([x, () => y.value], ([newX, newY]) => {
        console.log(`x is ${newX} and y is ${newY}`)
      })
      

      注意,你不能直接偵聽響應式對象的屬性值,例如:

      const obj = reactive({ count: 0 })
      
      // 錯誤,因為 watch() 得到的參數是一個 number
      watch(obj.count, (count) => {
        console.log(`Count is: ${count}`)
      })
      

      這里需要用一個返回該屬性的 getter 函數:

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

      深層偵聽器

      直接給 watch() 傳入一個響應式對象,會隱式地創建一個深層偵聽器——該回調函數在所有嵌套的變更時都會被觸發。

      const obj = reactive({ count: 0 })
      
      watch(obj, (newValue, oldValue) => {
        // 在嵌套的屬性變更時觸發
        // 注意:`newValue` 此處和 `oldValue` 是相等的
        // 因為它們是同一個對象!
      })
      
      obj.count++
      

      相比之下,一個返回響應式對象的 getter 函數,只有在返回不同的對象時,才會觸發回調:

      watch(
        () => state.someObject,
        () => {
          // 僅當 state.someObject 被替換時觸發
        }
      )
      

      你也可以給上面這個例子顯式地加上 deep 選項,強制轉成深層偵聽器:

      watch(
        () => state.someObject,
        (newValue, oldValue) => {
          // 注意:`newValue` 此處和 `oldValue` 是相等的
          // *除非* state.someObject 被整個替換了
        },
        { deep: true }
      )
      

      即時回調的偵聽器

      watch 默認是懶執行的:僅當數據源變化時,才會執行回調。如果我們希望在創建偵聽器時,立即執行一遍回調。舉例來說,我們想請求一些初始數據,然后在相關狀態更改時重新請求數據。

      我們可以通過傳入 immediate: true 選項來強制偵聽器的回調立即執行:

      watch(
        source,
        (newValue, oldValue) => {
          // 立即執行,且當 `source` 改變時再次執行
        },
        { immediate: true }
      )
      

      一次性偵聽器

      每當被偵聽源發生變化時,偵聽器的回調就會執行。如果希望回調只在源變化時觸發一次,請使用 once: true 選項。

      watchEffect

      watchEffect() 允許我們自動跟蹤回調的響應式依賴。

      const todoId = ref(1)
      const data = ref(null)
      
      watch(
        todoId,
        async () => {
          const response = await fetch(
            `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
          )
          data.value = await response.json()
        },
        { immediate: true }
      )
      
      // 利用watchEffect偵聽器可以重寫為:
      watchEffect(async () => {
        const response = await fetch(
          `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
        )
        data.value = await response.json()
      })
      

      這個例子中,回調會立即執行,不需要指定 immediate: true。在執行期間,它會自動追蹤 todoId.value 作為依賴(和計算屬性類似)。每當 todoId.value 變化時,回調會再次執行。有了 watchEffect(),我們不再需要明確傳遞 todoId 作為源值。

      對于這種只有一個依賴項的例子來說,watchEffect() 的好處相對較小。

      但是對于有多個依賴項的偵聽器來說,使用 watchEffect() 可以消除手動維護依賴列表的負擔

      此外,如果你需要偵聽一個嵌套數據結構中的幾個屬性,watchEffect() 可能會比深度偵聽器更有效,因為它將只跟蹤回調中被使用到的屬性,而不是遞歸地跟蹤所有的屬性。

      注意watchEffect 僅會在其同步執行期間,才追蹤依賴。在使用異步回調時,只有在第一個 await 正常工作前訪問到的屬性才會被追蹤。

      watch vs. watchEffect

      watchwatchEffect 都能響應式地執行有副作用的回調。它們之間的主要區別是追蹤響應式依賴的方式

      • watch 只追蹤明確偵聽的數據源。它不會追蹤任何在回調中訪問到的東西。另外,僅在數據源確實改變時才會觸發回調。watch 會避免在發生副作用時追蹤依賴,因此,我們能更加精確地控制回調函數的觸發時機
      • watchEffect,則會在副作用發生期間追蹤依賴。它會在同步執行過程中,自動追蹤所有能訪問到的響應式屬性。這更方便,而且代碼往往更簡潔,但有時其響應性依賴關系會不那么明確。

      副作用清理

      一個回調函數,當偵聽器失效準備重新運行時會被調用。

      onWatcherCleanup()

      import { watch, onWatcherCleanup } from 'vue'
      
      watch(id, (newId) => {
        const controller = new AbortController()
      
        fetch(`/api/${newId}`, { signal: controller.signal }).then(() => {
          // 回調邏輯
        })
      
        onWatcherCleanup(() => {
          // 終止過期請求
          controller.abort()
        })
      })
      

      onWatcherCleanup 僅在 Vue 3.5+ 中支持,并且必須在 watchEffect 效果函數或 watch 回調函數的同步執行期間調用你不能在異步函數的 await 語句之后調用它。

      onCleanup()

      作為替代,onCleanup 函數還作為第三個參數傳遞給偵聽器回調,以及 watchEffect 作用函數的第一個參數:

      watch(id, (newId, oldId, onCleanup) => {
        // ...
        onCleanup(() => {
          // 清理邏輯
        })
      })
      
      watchEffect((onCleanup) => {
        // ...
        onCleanup(() => {
          // 清理邏輯
        })
      })
      

      這在 3.5 之前的版本有效。此外,通過函數參數傳遞的 onCleanup 與偵聽器實例相綁定,因此不受 onWatcherCleanup 的同步限制。

      回調的觸發時機

      當你更改了響應式狀態,它可能會同時觸發 Vue 組件更新和偵聽器回調。

      類似于組件更新,用戶創建的偵聽器回調函數也會被批量處理以避免重復調用。例如,如果我們同步將一千個項目推入被偵聽的數組中,我們可能不希望偵聽器觸發一千次。

      默認情況下,偵聽器回調會在父組件更新 (如有) 之后、所屬組件的 DOM 更新之前被調用。這意味著如果你嘗試在偵聽器回調中訪問所屬組件的 DOM,那么 DOM 將處于更新前的狀態。

      Post Watchers

      如果想在偵聽器回調中能訪問被 Vue 更新之后的所屬組件的 DOM,你需要指明 flush: 'post' 選項:

      watch(source, callback, {
        flush: 'post'
      })
      
      watchEffect(callback, {
        flush: 'post'
      })
      

      后置刷新的 watchEffect() 有個更方便的別名 watchPostEffect()

      同步偵聽器

      你還可以創建一個同步觸發的偵聽器,它會在 Vue 進行任何更新之前觸發:

      watch(source, callback, {
        flush: 'sync'
      })
      
      watchEffect(callback, {
        flush: 'sync'
      })
      

      同步觸發的 watchEffect() 有個更方便的別名 watchSyncEffect()

      import { watchSyncEffect } from 'vue'
      
      watchSyncEffect(() => {
        /* 在響應式數據變化時同步執行 */
      })
      

      停止偵聽器

      setup()<script setup> 中用同步語句創建的偵聽器,會自動綁定到宿主組件實例上,并且會在宿主組件卸載時自動停止。因此,在大多數情況下,你無需關心怎么停止一個偵聽器。

      一個關鍵點是,偵聽器必須用同步語句創建:如果用異步回調創建一個偵聽器,那么它不會綁定到當前組件上,你必須手動停止它,以防內存泄漏。如下方這個例子:

      <script setup>
      import { watchEffect } from 'vue'
      
      // 它會自動停止
      watchEffect(() => {})
      
      // ...這個則不會!
      setTimeout(() => {
        watchEffect(() => {})
      }, 100)
      </script>
      

      要手動停止一個偵聽器,請調用 watchwatchEffect 返回的函數:

      const unwatch = watchEffect(() => {})
      
      // ...當該偵聽器不再需要時
      unwatch()
      

      參考: Vue3 的 watch,你們都手動清除過嗎?

      posted @ 2025-04-10 00:27  CD、小月  閱讀(64)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲第一尤物视频在线观看导航 | 国产精品中文字幕综合| 成人3d动漫一区二区三区| 四虎永久免费精品视频| 久久天天躁狠狠躁夜夜avapp | 国产明星精品无码AV换脸| 国产乱码1卡二卡3卡四卡5| 国产午夜亚洲精品不卡网站| 潮喷失禁大喷水无码| 国产中文字幕精品视频| 中文字幕亚洲精品第一页| 2021亚洲国产精品无码| 被灌满精子的波多野结衣 | 免费现黄频在线观看国产| 成人3D动漫一区二区三区| 国产丰满乱子伦午夜福利| 国产情侣激情在线对白| 国产极品美女高潮无套| 亚洲国产精品自产在线播放| 亚洲国产免费图区在线视频| 噜噜综合亚洲av中文无码| 国厂精品114福利电影免费| 日韩免费美熟女中文av| 全免费A级毛片免费看无码| 国产成人欧美一区二区三区在线| 女人被狂躁c到高潮| 岛国一区二区三区高清视频| 国产精品无码a∨麻豆| 国产又黄又湿又刺激网站| 国产午夜精品理论大片| 久久这里都是精品二| 少妇激情a∨一区二区三区| 鲁山县| 国产日韩入口一区二区| 国产一级片内射在线视频| 日本高清免费不卡视频| 妺妺窝人体色www婷婷| 免费观看日本污污ww网站| 九九热在线视频免费观看| 亚洲色欲色欱WWW在线| 香蕉久久久久久久AV网站|