vue2的響應式:
核心:
對象:通過defineProperty對對象的已有屬性值的讀取和修改進行劫持監視/攔截
數組:通過重寫數組更新數組的一系列更新元素的方法來實現元素修改的劫持
Object.defineProperty(data, 'count',{
get(){},
set(){}
})
問題:
對象直接新添加的屬性或刪除已有屬性,界面不會自動更新
直接通過下標替換元素或更新length,界面不會自動更新arr[1]={}
vue3的響應式
核心:
通過Proxy(代理):攔截對data任意屬性的任意(13種)操作,包括屬性值的讀寫,屬性的添加,屬性的刪除等...
通過 Reflect(反射):動態對被代理對象的相應屬性進行特定的操作
Proxy意思就是代理,它的作用是對對象進行攔截,以及數據讀取、修改的過濾保護
//假設一個數據對象data,內容為:
var data = {
username: 'Frank',
age: 26
}
現在我們給data創建一個代理proxy
var proxy = new Proxy(data, {set: function(){...}, get: function(){...} })
那么,如果我們需要修改數據,比如正常時:data.username='frank'
有了代理之后是這樣:proxy.username='frank'
簡單來說,proxy擁有data的屬性和權限。
我們在使用Proxy時我們需要用new調用,例如
const p = new Proxy(target, handler)
參數target:是Proxy要包裝的目標對象,可以是任意類型的對象,包括原生數組,函數,甚至是另一個代理
參數handler:是一個通常以函數作為屬性的對象,各屬性中的函數分別定義了在執行各種操作時代理p的行為(通俗的說它就是一個處理器,用來監視數據的變化)。它重點的監視方法主要是:handler.get()讀取屬性值,handler.set()更新屬性值,handler.deleteProperty()刪除屬性值
Reflect是一個內置的對象,它提供攔截JavaScript操作的方法。這些方法與proxy handlers的方法相同。Reflect不是一個函數對象,因此它是不可構造的,不能通過new來調用也不能將它作為一個函數來調用。Reflect的所有屬性和方法都是靜態的。(通俗的說就是通過反射對象可以把當前的代理對象/目標對象的屬性的屬性值給反射回去)
new Proxy(date, {
//攔截獲取屬性值---》讀取數據
get(target, prop){
return Reflect.get(target, prop)
},
//攔截設置屬性值或添加屬性值-----》寫入數據
set(target, prop, value){
return Reflect.set(target, prop, value)
}
//攔截刪除屬性
deleteProperty(target, prop){
return Reflect.deleteProperty(target, prop)
}
})
proxy
文檔:
Proxy: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
Reflect: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect