首頁 >web前端 >Vue.js >vue3響應式Proxy與Reflect如何使用

vue3響應式Proxy與Reflect如何使用

WBOY
WBOY轉載
2023-06-03 10:59:121468瀏覽

    理解Proxy與Reflect

    vue3的回應式離不開Proxy,說到Proxy則離不開Reflect.這兩個物件是ES6新增的對象,同時在程式設計領域,他們也代表著2種設計模式,即代理與反射。

    Proxy

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

    ES6 原生提供 Proxy 建構函數,用來產生 Proxy 實例。

    var proxy = new Proxy(target, handler);

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

    vue3響應式Proxy與Reflect如何使用

    Reflect

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

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

    vue3響應式Proxy與Reflect如何使用

    它的運算和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,這樣響應式就不會丟失了。

    以上是vue3響應式Proxy與Reflect如何使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除