vue3已經從Object.property
更換成Proxy
,Proxy
比起前者可以直接監聽物件數組,對於深層的物件和數組,會把觸發對應getter
,然後去遞歸進行依賴收集,並不是直接像vue2
暴力那樣遞歸,總體而言性能更好
對reactive傳進來的對象進行Proxy進行劫持在內部進行依賴收集與通知更新操作
function reactive(raw) { return new Proxy(raw, { get(target, key) { const res = Reflect.get(target, key); //添加依赖 track(target, key as string); return res; }, set(target, key, value) { const res = Reflect.set(target, key, value); trigger(target, key); return res; }, }); }
採用Reflet
對物件進行標準化操作,因為如果直接採用JS如果失敗了,不會產生異常提示
這樣在進行獲取資料是後進行依賴收集,在更新資料後進行通知依賴更新
接下來便介紹依賴收集是什麼樣子
const targetMap = new WeakMap(); function track(target, key) { let depsMap = targetMap.get(target); if (!depsMap) { depsMap = new Map(); targetMap.set(target, depsMap); } let dep = depsMap.get(key); if (!dep) { dep = new Set(); depsMap.set(key, dep); } dep.add(currentEffect); }
首先是一個WeakMap-->然後使用者透過target取得對應的內部Map-->然後透過key取得到Set集合,內部便是儲存的一個依賴。其實依賴收集的過程就是這樣。
這裡使用WeakMap原因是它是一個弱引用,不會影響垃圾回收機制回收。
那麼currentEffect
到底是個什麼東西呢?實際上是ReactiveEffect
中正在運行的類別
class ReactiveEffect { private fn: Function; constructor(_fn: Function) { this.fn = _fn; } run() { currentEffect = this; this.fn(); } } let currentEffect: null | ReactiveEffect = null; function effect(fn: Function) { const reactiveEffect = new ReactiveEffect(fn); reactiveEffect.run(); }
後續會詳情講解,目前可以就把他理解成一個依賴,用戶使用了effect函數過後,裡面的響應式資料發生變更後會重新執行傳遞進去的回呼函數
vue2中收集的依賴對應watcher,vue3收集的依賴實際上是effect,他們兩者實作功能其實是一樣的。
這裡暫不考慮DOM
問題,操作起來其實很簡單就是透過被Proxy
劫持的target
與key
找到對應的Set集合呼叫使用者傳遞的fn
函數進行依賴更新
function trigger(target, key) { let depsMap = targetMap.get(target); let dep = depsMap.get(key); for (let effect of dep) { effect.fn(); } }
以上是vue3 reactive響應式依賴收集派發更新原理是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!