vue data裡的資料的變化
實際在開發過程中發現,我們列印data裡的資料的時候會發現,他不是我們所看到的以往的很平常的格式,他是一個proxy的格式的,如下圖:
也就是說無論是什麼型別的資料,都會在外面包一層proxy的包裝;
這個是作什麼的呢?
查資料——————————————
經過這一頓操作之後,資料就可以恢復正常的型別了,
JSON.parse(JSON.stringify(val))
關於Proxy:
Proxy可以理解成,在目標物件之前架設一層 "攔截",當外界對該物件訪問的時候,都必須經過這層攔截,而Proxy就充當了這種機制,類似於代理的含義,它可以對外界訪問物件之前進行過濾和改寫該物件。
如果對vue2.0瞭解或看過原始碼的人都知道,vue2.0中使用 Object.defineProperty()方法對該物件通過 遞迴+遍歷的方式來實現對資料的監控的,
當我們使用陣列的方法或改變陣列的下標是不能重新觸發 Object.defineProperty中的set()方法的,因此就做不到實時響應了。所以使用 Object.defineProperty 存在如下缺點:
1. 監聽陣列的方法不能觸發Object.defineProperty方法中的set操作(如果要監聽的到話,需要重新編寫陣列的方法)。
2. 必須遍歷每個物件的每個屬性,如果物件巢狀很深的話,需要使用遞迴呼叫。
但是vue2.0就是用$set()方法去解決上面的這個問題,Vue3.0呢進行了升級,那就是Proxy。
Proxy基本語法
const obj = new Proxy(target, handler);
這裡就和上面的截圖對應上了,有木有發現呢~,再來一個詳細的圖;
引數說明如下:
target:被代理物件。
handler:是一個物件,聲明瞭代理target的一些操作。
obj:是被代理完成之後返回的物件。
但是當外界每次對obj進行操作時,就會執行handler物件上的一些方法。handler中常用的物件方法如下:
1. get(target, propKey, receiver)
2. set(target, propKey, value, receiver)
3. has(target, propKey)
4. construct(target, args):
5. apply(target, object, args)
如下程式碼演示:
const target = {
name: 'kongzhi'
};
const handler = {
get: function(target, key) {
console.log(`${key} 被讀取`);
return target[key];
},
set: function(target, key, value) {
console.log(`${key} 被設定為 ${value}`);
target[key] = value;
}
};
const testObj = new Proxy(target, handler);
/*
獲取testObj中name屬性值
會自動執行 get函式後 列印資訊:name 被讀取 及輸出名字 kongzhi
*/
console.log(testObj.name);
/*
改變target中的name屬性值
列印資訊如下: name 被設定為 111
*/
testObj.name = 111;
console.log(target.name); // 輸出 111
如上程式碼所示:也就是說 target是被代理的物件,handler是代理target的,那麼handler上面有set和get方法,當每次列印target中的name屬性值的時候會自動執行handler中get函式方法,當每次設定 target.name 屬性值的時候,會自動呼叫 handler中的set方法,因此target物件對應的屬性值會發生改變,同時改變後的 testObj物件也會發生改變。同理改變返回後 testObj物件中的屬性也會改變原物件target的屬性的,因為物件是引用型別的,是同一個引用的。如果這樣還是不好理解的話,可以簡單的看如下程式碼應該可以理解了:
const target = {
name: 'kongzhi'
};
const testA = target;
testA.name = 'xxx';
console.log(testA.name); // 列印 xxx
console.log(target.name); // 列印 xxx
大概就是這樣的,vue3.0的升級,可直接監聽陣列型別的資料變化
監聽的目標為物件本身,不需要像Object.defineProperty一樣遍歷每個屬性,有一定的效能提升。