Vue3都使用Proxy了,你更應該了解Proxy

2021-09-28 20:59:53 字數 2822 閱讀 3581

vue3.0的pre-alpha版**已經開源了,就像作者之前放出的訊息一樣,其資料響應這一部分已經由es6的proxy來代替object.defineproperty實現,感興趣的同學可以看其實現原始碼。vue都開始使用proxy來實現資料的響應式了,所以有必要抽點時間了解下proxy。

說到proxy,就不得不提object.defineproperty,我們都知道,vue3.0之前的版本都是使用該方法來實現資料的響應式,具體是:

通過設定物件屬性getter/setter方法來監聽資料的變化,同時getter也用於依賴收集,而setter在資料變更時通知訂閱者更新檢視。

大概如下**所示:

function definereactive(obj, key, value) ,

set(newval) }})

}function observe(obj)

object.keys(obj).foreach(key => )

}var data =

observe(data)

雖然object.defineproperty通過為屬性設定getter/setter能夠完成資料的響應式,但是它並不算是實現資料的響應式的完美方案,某些情況下需要對其進行修補或者hack,這也是它的缺陷,主要表現在兩個方面:

無法檢測到物件屬性的新增或刪除

由於js的動態性,可以為物件追加新的屬性或者刪除其中某個屬性,這點對經過object.defineproperty方法建立的響應式物件來說,只能追蹤物件已有資料是否被修改,無法追蹤新增屬性和刪除屬性,這就需要另外處理。

目前vue保證響應式物件新增屬性也是響應式的,有兩種方式:

響應式物件刪除屬性,可以使用vue.delete(obj, propertyname/index)或者vue.$delete(obj, propertyname/index); 類似於刪除響應式物件子物件的某個屬性,也可以重新給子物件賦值來解決。

不能監聽陣列的變化

vue在實現陣列的響應式時,它使用了一些hack,把無法監聽陣列的情況通過重寫陣列的部分方法來實現響應式,這也只限制在陣列的push/pop/shift/unshift/splice/sort/reverse七個方法,其他陣列方法及陣列的使用則無法檢測到,例如如下兩種使用方式:

那麼vue怎麼實現陣列的響應式呢,並不是重寫陣列的array.prototype對應的方法,具體來說就是重新指定要運算元組的prototype,並重新該prototype中對應上面的7個陣列方法,通過下面**簡單了解下實現原理:

const methods = ['pop','shift','unshift','sort','reverse','splice', 'push'];

// 複製array.prototype,並將其prototype指向array.prototype

let proto = object.create(array.prototype);

methods.foreach(method =>

})function observe(obj)

if (typeof obj === 'object')

}

proxy,字面意思是**,是es6提供的乙個新的api,用於修改某些操作的預設行為,可以理解為在目標物件之前做一層攔截,外部所有的訪問都必須通過這層攔截,通過這層攔截可以做很多事情,比如對資料進行過濾、修改或者收集資訊之類。借用proxy的巧用的一幅圖,它很形象的表達了proxy的作用。

es6原生提供的proxy建構函式,用法如下:

var proxy = new proxy(obj, handler)
其中obj為proxy要攔截的物件,handler用來定製攔截的操作,返回乙個新的**物件proxy;proxy**特點:

proxy**目標物件,是通過操作上面的13種trap來完成的,這與es6提供的另乙個apireflect的13種靜態方法一一對應。二者一般是配合使用的,在修改proxy**物件時,一般也需要同步到**的目標物件上,這個同步就是用reflect對應方法來完成的。例如上面的reflect.set(target, key, value)同步目標物件屬性的修改。需要補充一點:

13種trap操作方法中,若初始化時handler沒設定的方法就直接操作目標物件,不會走攔截操作

proxy因為在目標物件之前架設了一層攔截,外部對該目標物件的訪問都必須經過這次攔截。那麼通過這層攔截,可以做很多事情,例如控制過濾、快取、資料驗證等等,可以說proxy的使用場景比較廣,下面簡單列舉幾個使用場景,更多實用場景可以參考proxy的巧用。

雖然proxy相對於object.defineproperty有很有優勢,但是並不是說proxy就沒有劣勢,這主要表現在以下兩個方面:

效能問題

proxy的另乙個就是效能問題,為此有人專門做了乙個對比實驗,原文在這裡thoughts-on-es6-proxies-performance,對應的中文翻譯可以參考es6 proxy效能之我見。proxy的效能比promise還差,這就要需要在效能和簡單實用上進行權衡。例如vue3使用proxy後,其對物件及陣列的攔截很容易實現資料的響應式,尤其對陣列來說。

另外,proxy作為新標準將受到瀏覽器廠商重點持續的效能優化,效能這塊相信會逐步得到改善。

vue3實現響應式原理 Proxy

vue3 回顧object.definepropery的缺點 1.基本使用const data const data a b c const proxydata newproxy data,const result reflect.get target,key,receiver return res...

Vue3使用總結

vue3官方文件 vue3使用文件 vue3學習筆記 名稱 作用區別 ref用於為物件新增響應式狀態,基本資料型別作為引數,返回乙個具有響應式狀態的副本。1 獲取資料值的時候需要加.value。2 可以理解為ref是通過reactive包裝了一層具有value屬性的物件實現的。3 引數可以傳遞任意資...

vue3安裝 你期待已久的Vue 3 正式發布啦

vue.js 3.0 one piece 已正式發布,此框架新的主要版本提供了更好的效能 更小的 包體積 更好的 typescript 整合 用於處理大規模用例的新 api,並為框架未來的長期迭代奠定了堅實的基礎。3.0 版本的開發周期長達兩年多,期間產生了 30 rfcs 2600 commits...