點燈坊

失くすものさえない今が強くなるチャンスよ

computed()、watch()、 watchEffect()

Sam Xiao's Avatar 2024-02-01

Vue 提供了三個 Reactivity API:computed()watch()watchEffect(),三者很類似,但又不完全相同。

Version

Vue 3.4

Behavior

  • computed():一開始會執行一次
  • watch():一開始不執行,追蹤的 state 改變才會執行
  • watchEffect():一開始會執行一次

Parameter

  • computed():不可傳參數,若要傳參數改用一般 function
  • watch():可傳參數,第一個參數為 newValue,第二個參數為 oldValue
  • watchEffect():不可傳參數

Sychoronous / Asynchronous

  • computed():只能 同步 (不能 call API)
  • watch()同步非同步 皆可
  • watchEffect()同步非同步 皆可

Side Effect

  • computed():不可處理 Side Effect (Pure Function)
  • watch():專門處理 Side Effect
  • watchEffect():專門處理 Side Effect

Return

  • computed():回傳結果
  • watch():無回傳結果,執行傳入 function
  • watchEffect():無回傳結果,執行傳入 function

Tracking Target

  • computed():可追蹤 state、computed
  • watch():可追蹤 state、computed 或 array
  • watchEffect():可追蹤 function 內 同步 的 state、computed 或 array,但不追蹤 非同步 的 state、computed 或 array

Effeciency

  • computed():支援 cache
  • watch():不支援 cache
  • watchEffect():不支援 cache

Maintainability

  • computed():可在 HTML template 中直接發現 computed 被使用,然後一直 trace function 即可,容易 debug
  • watch():常會沒發現原來有個 state 或 computed 被 watch 偷偷修改,因為在 trace function 時無法發現有 watch() 存在,不容易 debug
  • watchEffect():常會沒發現原來有個 state 或 computed 被 watch 偷偷修改,因為在 trace function 時無法發現有 watchEffect() 存在,不容易 debug

Usage

  • computed()90% 盡量使用 computed 實現
  • watch()5% 僅用於 edge case、特例或 computed 難以實現時
  • watchEffect()5% 僅用於 edge case、特例 或 computed 難以實現時

Conclusion

  • computed():適合單純用來加工資料,如 HTML Template 上的顯示,
  • watch():追蹤單一 state,且傳入 function 想根據新舊資料進行處理,如 route 參數變化重新發 API
  • watchEffect():追蹤多個 state,且一開始會執行一次,如輸入變化會重新發 API,但有提供預設值可先執行一次
  • 有些需求用 computed()watch()watchEffect() 都可實現時,優先使用 computed(),這是效率最好的方式,也是可讀性最高,最容易維護方式, 而 watch()watchEffect() 常常會讓人忽略原來還有代碼寫在這裡