首先,Vue 是一個 MVVM 框架,雙向綁定資料與畫面。
而在 Vue 3 出現之前,Vue 使用的都是 Object.defineProperty 來實現雙向綁定資料劫持,監測數據的變動。
Object.defineProperty 會直接對一個物件定義、或是修改現有的屬性。執行後會回傳定義完的物件。
(以上是 MDN 的說明)
語法 : Object.defineProperty(obj, prop, descriptor)
Object.defineProperty 提供三個參數,分別為 :
1.obj:要定義或修改的物件
2.prop : 要定義或修改的屬性(key)的名字
3.descriptor : 目標屬性要有的特性
這三個都是必填的。
var obj = {}
//對目前的物件增加描述
Object.defineProperty(obj,"test",{
configurable:true | false,
enumerable:true | false,
value:(這裡填 value),
writable:true | false
});
現在就來介紹一下 descriptor 描述符的這幾個屬性吧 :
注意 : get 與 set 無法與 value, writable 共用,否則報錯。
注意 : 若使用了 getter 或 setter,就不能使用 writable 和 value 這兩種屬性。
注意 : get、set可以只出現其中一個,也可以兩個都一起出現。如果不設置的話,兩者預設為 undefined。
而我們可以透過 get / set
方法來實現畫面與資料的響應 :
var obj = {};
var value1 = 'hello';
Object.defineProperty(obj,"test",{
get:function (){
// 取值時觸發
return value1;
},
set:function (value){
//賦值時觸發,並取得新值
value1 = value;
}
});
//取值
console.log( obj.newKey ); //hello
//賦值
obj.newKey = '變成 value2拉~';
console.log( obj.newKey ); //變成 value2拉~
我們在大物件內可以同時插入屬性與要調整的特徵~
Object.defineProperties(obj,{
a:{
writable:false
},
b:{
value:3
}
})
那你說為什麼 Vue 3 拋棄了 Object.defineProperty 呢?
因為它也是有缺點的:
無法監聽陣列的變化 (其實是可以,但尤大表示由於效能問題,沒有在 Vue2 加入此功能)
只能劫持物件的屬性,如果物件內有巢狀結構的話就需要進行深度遍歷。
比如我們在Obj的物件裡面加一個 d 屬性,並設定不可寫入,所以我們無法改動 d 屬性的值。
Object.defineProperty(obj,d,{
value:{},
writable:false
})
但如果今天 d 屬性是一個物件呢?我們在 obj.d 再賦予一個 a 屬性的話,這樣改的動嗎?
答案是 可以,由此可知 Object.defineProperty 只能給予淺層保護。
Object.defineProperty(obj,d,{
value:{},
writable:false
})
person.d.a = 6
因此 Vue3 中就改用 proxy 啦~
那麼今天就先到這,明天來談談 Vue 3 的雙向綁定原理吧 !
參考文章 :
淺談 Vue2 雙向綁定的概念與實作
JavaScript 核心觀念(54)- 物件屬性延伸章節:屬性的特徵 - 屬性特徵是什麼?
vue2.x和vue3.x双向绑定原理的区别,以及vue3.x双向绑定的深入解析
重新理解 Vue 的雙向綁定
理解Object.defineProperty的作用
记一次思否问答的问题思考:Vue为什么不能检测数组变动
為什麼Vue3.0 不再使用defineProperty實現資料監聽