iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
自我挑戰組

程式小白的 vue.js 學習筆記系列 第 8

Day8 : Vue2 的雙向綁定原理 : Object.defineProperty

  • 分享至 

  • xImage
  •  

首先,Vue 是一個 MVVM 框架,雙向綁定資料與畫面。

而在 Vue 3 出現之前,Vue 使用的都是 Object.defineProperty 來實現雙向綁定資料劫持,監測數據的變動。

Object.defineProperty

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 描述符的這幾個屬性吧 :

  1. value : 屬性的值,預設為 undefined。
  2. writable : 是否能被重寫。 若為 true 代表可被重寫、false代表不可被重寫。預設為false。
  3. configurable : 是否能設定(或刪除)屬性的特性(比如 writable, configurable, enumerable等等)。預設為false,但如果初次定義時設定成 true 的話,則第二次將報錯)
  4. enumerable : 是否能被列舉 (使用for...in 或 Object.keys())
  5. get / set : 取值時會觸發 get、賦值會觸發set(函式)。

注意 : 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

我們在大物件內可以同時插入屬性與要調整的特徵~

Object.defineProperties(obj,{
   a:{
       writable:false
   },
   b:{
       value:3
   }
})

Object.defineProperty 的缺點?

那你說為什麼 Vue 3 拋棄了 Object.defineProperty 呢?

因為它也是有缺點的:

  1. 無法監聽陣列的變化 (其實是可以,但尤大表示由於效能問題,沒有在 Vue2 加入此功能)

  2. 只能劫持物件的屬性,如果物件內有巢狀結構的話就需要進行深度遍歷。
    比如我們在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

  1. 對物件中新增的屬性需要手動的 Observe (使用$set)(參考 這篇文章)

因此 Vue3 中就改用 proxy 啦~

那麼今天就先到這,明天來談談 Vue 3 的雙向綁定原理吧 !


參考文章 :
淺談 Vue2 雙向綁定的概念與實作
JavaScript 核心觀念(54)- 物件屬性延伸章節:屬性的特徵 - 屬性特徵是什麼?
vue2.x和vue3.x双向绑定原理的区别,以及vue3.x双向绑定的深入解析
重新理解 Vue 的雙向綁定
理解Object.defineProperty的作用
记一次思否问答的问题思考:Vue为什么不能检测数组变动
為什麼Vue3.0 不再使用defineProperty實現資料監聽


上一篇
Day 7 : Vue 的各種綁定(二) : v-model 資料雙向綁定
下一篇
Day9 : Vue3 的雙向綁定原理 : Proxy
系列文
程式小白的 vue.js 學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言