reactive readonly嵌套對象轉(zhuǎn)換功能實現(xiàn)詳解
一、單元測試
reactive
// src/reactivity/tests/reactive.spec.ts
it('nested reactive', () => {
const original = {
nested: { foo: 1 },
array: [{ bar: 2 }]
};
const observed = reactive(original);
expect(isReactive(observed.nested)).toBe(true);
expect(isReactive(observed.array)).toBe(true);
expect(isReactive(observed.array[0])).toBe(true);
});
readonly
it('nested readonly', () => {
const original = { foo: 1, bar: { baz: 2 } };
const wrapped = readonly(original);
expect(isReadonly(wrapped)).toBe(true);
expect(isReadonly(wrapped.bar)).toBe(true);
});
二、代碼實現(xiàn)
為什么嵌套的深層對象沒有轉(zhuǎn)換成reactive、readonly呢?
因為Proxy劫持的是對象本身,并不能劫持子對象的變化。
其實通過單測可以看出,我們只需要將reactive嵌套的里層對象也轉(zhuǎn)換成reactive,將readonly嵌套的里層對象也轉(zhuǎn)換成readonly。
那只需要在get中,返回res的時候,將res轉(zhuǎn)換成相應(yīng)的代理就可以了。
function createGetter(isReadonly = false) {
return function get(target, key) {
const res = Reflect.get(target, key);
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly;
}
if (isObject(res)) {
return isReadonly ? readonly(res) : reactive(res);
}
if (!isReadonly) {
track(target, key);
}
return res;
};
}
跑一下完整的單測結(jié)果看下:

ps: 其實這里需要注意的一點就是,在get中處理嵌套轉(zhuǎn)換,我們只有在用到這個子對象的時候,才會將這個子對象 轉(zhuǎn)換成響應(yīng)時代理,避免了不必要的性能浪費。對比vue2的遞歸遍歷defineProperty來說,也是一個優(yōu)化的地方。
以上就是reactive readonly嵌套對象轉(zhuǎn)換功能實現(xiàn)詳解的詳細內(nèi)容,更多關(guān)于reactive readonly嵌套對象轉(zhuǎn)換的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決echarts圖表y軸數(shù)據(jù)間隔過大的問題
這篇文章主要介紹了解決echarts圖表y軸數(shù)據(jù)間隔過大的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
vue2.0 element-ui中el-select選擇器無法顯示選中的內(nèi)容(解決方法)
這篇文章主要介紹了vue2.0 element-ui中的el-select選擇器無法顯示選中的內(nèi)容,在文中小編使用的是element-ui V2.2.3。具體解決方法及示例代碼大家參考下本文2018-08-08
vue3?el-table結(jié)合seamless-scroll實現(xiàn)表格數(shù)據(jù)滾動的思路詳解
這篇文章主要介紹了vue3?el-table結(jié)合seamless-scroll實現(xiàn)表格數(shù)據(jù)滾動,創(chuàng)建兩個table,隱藏第一個table的body部分,這樣就能得到一個固定的head,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07

