這是我以前被問到的一個問題,被問以前沒有想過,被問到的時候很懵😯 vue2的數據雙向綁定是用的這個Object.defineProperty,vue3會用proxy實現數據劫持。那vue3爲何會這麼作呢?vue
這個問題我以前試着描述過不少次,可是由於都自認爲不夠清楚。 vue是利用數據劫持結合發佈訂閱模式實現的數據雙向綁定。在vue的實現裏面,簡單來講有四部分:數組
1.Object.defineProperty的第一個缺陷,沒法監聽數組變化。 可是vue中是能夠監聽數組的變化的,那他是怎麼實現的呢?使用瞭如下八種方法:瀏覽器
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
複製代碼
實現示例參考:性能優化
const aryMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'];
const arrayAugmentations = [];
aryMethods.forEach((method)=> {
// 這裏是原生Array的原型方法
let original = Array.prototype[method];
// 將push, pop等封裝好的方法定義在對象arrayAugmentations的屬性上
// 注意:是屬性而非原型屬性
arrayAugmentations[method] = function () {
console.log('我被改變啦!');
// 調用對應的原生方法並返回結果
return original.apply(this, arguments);
};
});
let list = ['a', 'b', 'c'];
// 將咱們要監聽的數組的原型指針指向上面定義的空數組對象
// 別忘了這個空數組的屬性上定義了咱們封裝好的push等方法
list.__proto__ = arrayAugmentations;
list.push('d'); // 我被改變啦! 4
// 這裏的list2沒有被從新定義原型指針,因此就正常輸出
let list2 = ['a', 'b', 'c'];
list2.push('d'); // 4
複製代碼
以上代碼參考:這裏bash
2.Object.defineProperty的第二個缺陷,只能劫持對象的屬性,所以咱們須要對每一個對象的每一個屬性進行遍歷,若是屬性值也是對象那麼須要深度遍歷,顯然能劫持一個完整的對象是更好的選擇。app
1.proxy能夠直接監聽數組的變化; 2.proxy能夠監聽對象而非屬性.它在目標對象以前架設一層「攔截」,外界對該對象的訪問,都必須先經過這層攔截,所以提供了一種機制,能夠對外界的訪問進行過濾和改寫。 Proxy直接能夠劫持整個對象,並返回一個新對象。dom
本文參考:參考資料1mvvm