最新,Vue 改進了響應(yīng)式 API 中 Getter 的用法!
近日,Vue 改進了響應(yīng)式 API 中 getter 的用法,主要包括:
- 一個用于將不同來源(value / ref / getter)規(guī)范化為值的 API(通過引入 toValue())
- 一個用于將不同來源(value / ref / getter)規(guī)范化為引用的 API(通過增強 toRef())
- 引入 MaybeRef<T> 和 MaybeRefOrGetter<T> 類型
通常需要將狀態(tài)傳遞到組合式函數(shù)中并保持響應(yīng)性。在大多數(shù)情況下,這意味著要將響應(yīng)源轉(zhuǎn)換為 ref:
目前,toRef 僅用于從對象中“提取”單個屬性。這就有點不靈活,例如,如果想將嵌套屬性轉(zhuǎn)換為 ref:
上面的代碼有兩個問題:
- 調(diào)用 toRef 時 props.foo 可能不存在
- 如果 props.foo 被交換到不同的對象,這將無法處理這種情況。
為了解決這個問題,可以使用 computed:
但是,在這里使用 computed? 并不是最佳選擇。在內(nèi)部,computed? 創(chuàng)建一個單獨的 effect? 來緩存計算值。當 getter 只訪問屬性而不執(zhí)行任何昂貴的計算時,這實際上是很大的開銷。
將非引用響應(yīng)狀態(tài)傳遞到組合式函數(shù)的成本最低的方法就是用 getter? 包裝它(或“thunking”——即延遲實際值的訪問,直到調(diào)用 getter):
VueUse 已經(jīng)廣泛支持這種模式,這也有點類似于在 Solid 中看到的函數(shù)式 signals(信號)。
此外,這種模式在使用響應(yīng)式 props 解構(gòu)時會很常用:
引入 toValue()
在組合式函數(shù)中,其參數(shù)可以接受值或引用。這可以表示為:
為了也支持 getters,接受的類型將是:
目前提供的unref?將 MaybeRef<T>? 規(guī)范化為 T?。但是,不能讓 unref? 也解包 getter?,因為這將是一個破壞性的變化??梢栽诤瘮?shù)值上調(diào)用 unref 并期望返回該函數(shù)。這種情況比較少見,但仍然是無法破解的可能情況。
因此,引入一個新方法,toValue():
這就相當于 VueUse 的 [resolveUnref()](https://vueuse.org/shared/resolveUnref/)?。這里將其命名為 toValue()? 是因為它與 toRef() 相反:兩者代表兩個不同的規(guī)范化方向:
增強 toRef()
當然也可能存在需要 ref? 的情況——不能傳遞 getter?。對于這種情況,仍然可以使用 computed?。但如前所述,computed? 對于只訪問屬性的簡單 getter 來說是一種矯枉過正。
可以向 toRef()? 添加新的重載,以便它現(xiàn)在可以接受 getters :
以這種方式創(chuàng)建的 ref? 是只讀的,只是在每次訪問 .value? 時調(diào)用 getter。
toRef() 現(xiàn)在應(yīng)該被視為“將 value / ref / getter 規(guī)范化為 refs” 的 API:
這就相當于 VueUse 的 [resolveRef()](https://vueuse.org/shared/resolveRef/)。
現(xiàn)在仍然支持舊的 toRef(object, 'key')? 用法,但應(yīng)該首選更靈活的 getter 語法:
向后移植到 v2.7?
將這些功能添加在 v3.3 和 v2.7 之間造成了差異——雖然理論上不再回向 v2.7 添加新的功能,但這些可能值得向后移植以確保 vue-demi? 和依賴于 vue-demi 的 VueUse 的行為一致性。
如果向后移植到 2.7,VueUse 也可以用 toRef? 和 toValue? 來替換 resolveRef? 和 resolveUnref。
參考:https://github.com/vuejs/core/pull/7997