vue3響應式Proxy與Reflect的理解及基本使用實例詳解

正文

在第四章中,作者講述瞭Vue.js中響應式系統的設計與實現,這一塊其實是整個框架的基石,也是MVVM中,ViewModel(VM)的重要組成部分。 其實在上一章中我已經感覺很難瞭,有一些操作作者也隻是幾筆帶過,卻很值得我們思考。這一張中,我們將目光著重於響應式數據本身,來完善上一章中我們的demo。

理解Proxy與Reflect

vue3的響應式離不開Proxy,說到Proxy則離不開Reflect.這兩個對象是ES6新增的對象,同時在編程領域,他們也代表著2種設計模式,即代理與反射。設計模式都是後話,等我學會瞭也一定寫一篇文章分享一下🤪.

Proxy

Proxy 可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須經過這層攔截,而我們就可以通過這層攔截去改變目標對象的內容或者行為,或者叫過濾和控制。這個詞本意就是代理,好比一個代理人站在神奇,我們所有行為都會被他過濾,可能我們說的話,經過代理人一說,意思就變瞭。

ES6 原生提供 Proxy 構造函數,用來生成 Proxy 實例。

var proxy = new Proxy(target, handler);

其中target表示要代理的那個對象,handler則是表示我們需要攔截的行為,這裡直接放一張阮一峰的截圖。

Reflect

Reflect中文譯為:反射。如果說Proxy 是有一個代理人站在身前面,幫你攔截並處理一些行為,那麼Reflect就是你身後的一面鏡子,它能看見真實的自己。

而你自己,就是一個類或者對象,或者一個函數,隻要是js中存在的,都能被ProxyReflect處理。

它的操作和Proxy正好相反,但卻一一對應。比如我們獲取對象中一個屬性。

const obj = {foo:1}
const a = Reflect.get(obj, 'foo')

這一小節主要是介紹瞭Proxy與Reflect,後面會有一個應用老告訴你為什麼Proxy與Reflect與響應式數據息息相關。

實踐示例

看完瞭ProxyReflect的基本使用之後,我們實踐一下。

我們曾經寫過這樣的代碼

const reactive = (object)=>{
    return new Proxy(object,{
       get(target,key){
         track(target,key)
         return target[key]
       }
       set(target,key, newVal){
           target[key] = newVal
           trigger(target,key)
           return true
       }
    })
}

其實就是用Proxy代理瞭對象讀和取操作,在讀的時候收集依賴,在取的時候觸發響應。看起來似乎沒有問題,那麼我們再試繼續往下寫

const obj = {
    a:1,
    get b(){
      return this.a
    }
}
const data = reactive(obj)
effect(()=>{
    console.log(data.b)
})
setTimeOut(()=>{
    data.b++
},500)

這裡我們沒有用一般的對象寫法,而是通過訪問器為它新增瞭一個b屬性.之後,我們先把這個對象轉換為響應式對象,再給他們設定一個響應式的回調,然後在冬天改變他的值,理論上這時候應該會執行副作用函數,但是實際上呢,根本不會執行。

我們回顧一下之前寫的reactive方法,在裡面返回的是target[key],當我們的target是obj,key是b的時候,那個this會是誰呢?因為target是原始對象,也就是obj,根據誰調用是誰的原則,這個this也就指向瞭obj。obj是響應式對象嗎,顯然不是,那個b也就永遠不會執行副作用函數,響應式就失效瞭。

這裡其實就是this的指向問題,你可能會說一般人怎麼會用getter去賦值屬性呢,但是這個作為一個簡單的case,甚至都算不上邊界,我們需要解決它。

解決的方法也很簡單,就是通過Reflect。這也是為什麼我說ProxyReflect就是焦不離孟 孟不離焦. 我們的reactive,get的時候,加入第三個參數receiver

get(target,key){
    track(target,key,receiver)
    return Reflect.get(target,key,receiver)
}

我這裡理解的是,receiver就相當於函數的bind方法,它改變的this的執行,當我們同過Reflect讀取值的時候,this的指向被改為receiver,而Reflect時的receiver又是Proxy中的入參,它執行瞭這個Proxy,從而把前文中this的指向由obj改為data,這樣響應式就不會丟失瞭。

下一章中,作者會深入的介紹一下Proxy和一些相關的標準。

以上就是vue3響應式Proxy與Reflect的理解及基本使用實例詳解的詳細內容,更多關於vue3響應式Proxy Reflect的資料請關註WalkonNet其它相關文章!

推薦閱讀: