7_vue的資料代理,雙向繫結(更新中.......)

2022-10-22 12:01:09

回顧 object.defineProperty() 方法

區別

defineProperty == 給物件定義屬性用的

需要傳遞三個基本引數

  1. 需要定義屬性的物件名
  2. 你要定義的屬性叫什麼名字(比如給person這個實體新增一個age屬性)
  3. 設定項(物件型別的引數,裡面存放鍵值對)

<script>
    // 建立一個物件,該物件有兩個基本屬性
    var person = {
        name:"張三",
        sex:"男"
    }
    // 為person物件新增屬性
    // 1、給那個物件新增?
    // 2、新增的屬性名是什麼?
    // 3、這個屬性的基礎設定項(物件型別,鍵值對形式)
    Object.defineProperty(person,"age",{
        value:18, // 該屬性的值是
    })
</script>

需求1

  • 物件person,新增一個屬性age,有幾種方式?
  • 三種
    1. 直接在 person物件當中新增屬性;該屬性值可以修改
    2. 通過 .屬性;對其設定;該屬性值可以修改
    3. 通過 Object.finedProperty()進行新增;該屬性值不可列舉(不可修改) 預設情況下

不可列舉性

通過 defineProperty新增的屬性

如果不設定設定項,那麼該屬性是不可列舉的;在控制檯中可以看到,顏色變淺了

該屬性不參與遍歷,我們可以測試下

基本設定項

value

最開始設定的

enumerable

Object.defineProperty(person,"age",{
value:18, // 該屬性的值是
enumerable:true, // 該設定項控制新增的屬性是否參與列舉
})

writable

設定屬性是否可以被修改

configurable

控制屬性是否可以被刪除

沒有通過函數新增age屬性的person物件

通過函數新增age屬性的person物件刪除屬性

設定設定項刪除掉age屬性

需求2

  • 準備一個變數 number,值為18
  • person當中有一個age屬性,這個屬性的value 是 number(不是手寫的18)

問題所在

  • 這個變數的值可能會發生改變,如果呢?
  • 修改number,person物件當中的age值並沒有發生改變
  • 同理,修改age,number也不會發生改變

這倆好像有點關係,但好像又沒有關係,就js程式碼載入的時候這倆自頂而下有了這一層關係,但也僅僅只有這一層

那怎麼完成這個需求呢?

請看下方的高階設定項

高階設定項

get(getter)設定項

解析

  1. 它的資料型別是一個物件
  2. 有人讀取 person當中的age屬性的時候get就會被呼叫
  3. 且get的返回值就是age 的 value
  4. 自定義get(getter函數)的時候,不能再使用基礎設定了

那 返回一個 waves 字串吧

三個點兒

  1. invoke:對映
  2. property:屬性
  3. getter:get設定項 == 函數
    • get是屬性名
    • 他的型別是一個函數型別
    • 加在一起就是getter

  • age 屬性 是有的
  • 但是 value 是多少,目前不知道(...)
  • 想知道怎麼辦?點進去嘛

get函數


寫個程式碼測試一下,列印一句話

看樣子是的,我前面的措辭有問題

number與age進行關聯

對number值進行修改

那麼對age修改呢?

問題所在

  1. 一定是 先存取age
  2. 再呼叫getter
  3. 當number的value發生改變的時候
  4. 再次存取age,那麼就重新呼叫了getter函數
  5. 重新呼叫getter,會返回number,而這個number是修改過的,所以這邊資料是同步了

修改age;失敗

修改number,再存取age;成功

set(setter)設定項

同理,既然有get,那麼與之相輔相成的就是set

當你對age屬性進行修改的時候,set(setter)函數就被呼叫

且,呼叫的時候,會收到具體修改的 值

/**
* 需要傳遞一個引數value
* 被呼叫的時候,會收到具體修改的值
*/
set(value){
    // 當你對age屬性進行修改的時候,set(setter)函數就被呼叫
    // 被呼叫的時候,會收到具體修改的值
    console.log("pseron.age屬性發生修改,修改的值是",value);
}

測試

實現雙向繫結

  1. get函數
    • 實現了 number 與 age 的繫結,number發生修改的時候,age會發生變化
    • 當 age的值發生變化的時候,number值不變,所以無論怎麼修改,age的值 === number
  2. set函數
    • 實現了 age 與 number 的繫結,age的值發生變化的時候,number的值也會跟著變化
    • set函數會接到 age所修改的value,將value 賦值 給 number,完成雙向繫結

測試

總結

通過案例

  1. number 與 person,是兩個東西
  2. 但是藉助 Object.defineProperty,使二者進行了關聯
  3. person,確實是一個物件,age確實是person當中的屬性
  4. 但是呢?你現用,我現去給你取
    • 靠誰取? == get
    • 靠誰改? == set