<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          簡(jiǎn)單的了解下 Vue3 中 watch 與 watchEffect 的區(qū)別?

          共 2287字,需瀏覽 5分鐘

           ·

          2022-06-09 18:45


          來源 | https://www.zhihu.com/question/462378193/answer/1916657458

          你可以認(rèn)為他們是同一個(gè)功能的兩種不同形態(tài),底層的實(shí)現(xiàn)是一樣的。

          • watch- 顯式指定依賴源,依賴源更新時(shí)執(zhí)行回調(diào)函數(shù)

          • watchEffect - 自動(dòng)收集依賴源,依賴源更新時(shí)重新執(zhí)行自身

          響應(yīng)式依賴收集

          首先先需要了解一下 vue 3 的響應(yīng)式是怎么工作的。我想很多文章都詳細(xì)的講過這個(gè)部分了,這里就簡(jiǎn)單帶過一下。這里有個(gè)簡(jiǎn)化版的 ref 的實(shí)現(xiàn):

          const ref = (initialValue) => {  let _value = initialValue  return {    get value() {      track(this, 'value') // 收集依賴      return _value    },    set value() {      _value = value      trigger(this, 'value') // 觸發(fā)依賴    }  }}

          訪問數(shù)據(jù)時(shí),track 被呼叫并記錄下訪問了的字段。而當(dāng)寫入數(shù)據(jù)時(shí),trigger 被呼叫并觸發(fā)之前所依賴了這個(gè)字段所綁定事件更新(即 effect - computed, watch, watchEffect 底層都是 effect),他們會(huì)被記錄在一個(gè)全局的 WeakMap 中,這里就不展開了,感興趣可以去看源碼。

          const counter = ref(1)
          console.log(counter.value) // `track()` 被呼叫counter.value = 2 // `trigger()` 被呼叫

          當(dāng)我們需要函數(shù)里的依賴時(shí),只需要記錄函數(shù)執(zhí)行的過程中 track()被呼叫的次數(shù)(和對(duì)應(yīng)的對(duì)象與字段)即可。例如:

          const counter = ref(1)function foo() {  console.log(counter.value)}function collectDeps() {  startTracking()  foo() // 在這個(gè)過程中,counter 被收集  stopTracking()}

          這樣便可以知道 foo 這個(gè)函數(shù)依賴了 counter。

          Watch

          一個(gè) generalised 的 watch api 應(yīng)該是這樣的(其他類似直接接受 ref 或者 reactive 作為參數(shù)的其實(shí)都是糖)

          watch(  () => { /* 依賴源收集函數(shù) */ },  () => { /* 依賴源改變時(shí)的回調(diào)函數(shù) */ })

          這里的依賴源函數(shù)只會(huì)執(zhí)行一次,回調(diào)函數(shù)會(huì)在每次依賴源改變的時(shí)候觸發(fā),但是并不對(duì)回調(diào)函數(shù)進(jìn)行依賴收集。也就是說,依賴源和回調(diào)函數(shù)之間并不一定要有直接關(guān)系。

          WatchEffect

          watchEffect 相當(dāng)于將 watch 的依賴源和回調(diào)函數(shù)合并,當(dāng)任何你有用到的響應(yīng)式依賴更新時(shí),該回調(diào)函數(shù)便會(huì)重新執(zhí)行。

          不同于 watch,watchEffect 的回調(diào)函數(shù)會(huì)被立即執(zhí)行(即 { immediate: true })

          watchEffect(  () => { /* 依賴源同時(shí)是回調(diào)函數(shù) */ })

          以下兩種用法在行為上基本等價(jià)

          watchEffect(  () => console.log(counter.value))
          watch( () => counter.value, () => console.log(counter.value), { immediate: true })

          與 watch 不同的一點(diǎn)是,在 watchEffect 中依賴源會(huì)被重復(fù)執(zhí)行,動(dòng)態(tài)新增加的依賴也會(huì)被收集,例如

          const counter = ref(0)const enabled = ref(false)
          watchEffect(() => { if (enabled.value) console.log(counter.value)})// (以下忽略 nextTick)// watchEffect 會(huì)被立即執(zhí)行,因?yàn)?“enabled“ 為 false, 此時(shí)僅收集到 “enabled“ 依賴counter.value += 1 // 無反應(yīng)enabled.value = true // Effect 觸發(fā),控制臺(tái)出 "1"counter.value += 1 // “counter“ 被作為新的依賴被收集,控制臺(tái)出 "2"enabled.value = false // 函數(shù)被重新執(zhí)行,無輸出counter.value += 1 // 函數(shù)被重新執(zhí)行,無輸出 (雖然 counter 已經(jīng)沒有用了,但是作為依賴還是會(huì)觸發(fā)函數(shù))

          順帶一提,computed 其實(shí)類似一個(gè)帶輸出的同步版本的 watchEffect。

          什么時(shí)候用什么?

          推薦在大部分時(shí)候用 watch 顯式的指定依賴以避免不必要的重復(fù)觸發(fā),也避免在后續(xù)代碼修改或重構(gòu)時(shí)不小心引入新的依賴。watchEffect 適用于一些邏輯相對(duì)簡(jiǎn)單,依賴源和邏輯強(qiáng)相關(guān)的場(chǎng)景(或者懶惰的場(chǎng)景 )。

          寫在最后

          以上就是我今天跟你分享的內(nèi)容,如果你覺得有用的話,請(qǐng)點(diǎn)贊我,關(guān)注我,同時(shí)請(qǐng)將其分享給你身邊做開發(fā)的朋友,也許能夠幫助到他。

          最后,感謝你的閱讀,祝編程愉快!


          學(xué)習(xí)更多技能

          請(qǐng)點(diǎn)擊下方公眾號(hào)

          瀏覽 25
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大黄片AAA | 内射美女视频 | 亚洲少妇xxxx | 久久91蜜桃人妻无码系列 | 免费观看精品视频久久 |