詳解vue原理實(shí)現(xiàn)Object.defineProperty的應(yīng)用

vue中的mvvm就是數(shù)據(jù)雙向綁定,也就是數(shù)據(jù)model通過viewmodel影響視圖view,視圖view通過viewmodel影響數(shù)據(jù)model。那么他是具體怎么實(shí)現(xiàn)的呢?其實(shí)就是使用object.defineproperty進(jìn)行數(shù)據(jù)劫持和發(fā)布訂閱模式來實(shí)現(xiàn)。
格式:object.defineproperty(obj,'props',descriptor)
obj:要定義屬性的對(duì)象
props:要定義屬性的名稱
descriptor:要定義和修改的屬性描述

descriptor中常用的描述

configurable:為true時(shí)該屬性的描述符才能夠被改變,同時(shí)該屬性也能從對(duì)應(yīng)的對(duì)象上被刪除。
enumerable:為 true 時(shí),該屬性才會(huì)出現(xiàn)在對(duì)象的枚舉屬性中。就是可以用for循環(huán)輸出屬性
writable:為 true 時(shí),該屬性可以重新定義值
value:該屬性對(duì)應(yīng)的值??梢允侨魏斡行У?JavaScript 值(數(shù)值,對(duì)象,函數(shù)等)。
get:當(dāng)訪問該屬性時(shí),會(huì)調(diào)用此函數(shù)。執(zhí)行時(shí)不傳入任何參數(shù),但是會(huì)傳入 this 對(duì)象(由于繼承關(guān)系,這里的this并不一定是定義該屬性的對(duì)象)。該函數(shù)的返回值會(huì)被用作屬性的值。
set:當(dāng)屬性值被修改時(shí),會(huì)調(diào)用此函數(shù)。該方法接受一個(gè)參數(shù)(也就是被賦予的新值),會(huì)傳入賦值時(shí)的 this 對(duì)象。

var obj={}
Object.defineProperty(obj,'name',{
configurable:true,
get(){   //當(dāng)使用obj.name的時(shí)候回調(diào)用該函數(shù)方法
return ‘1’ //返回一個(gè)值
},set(val){ //當(dāng)使用obj.name=“2” ,則調(diào)用該函數(shù)方法
console.log(val)
}
})

當(dāng)使用set和get時(shí),不能使用value和writable描述
描述符默認(rèn)值匯總
擁有布爾值的鍵 configurable、enumerable 和 writable 的默認(rèn)值都是 false。
屬性值和函數(shù)的鍵 value、get 和 set 字段的默認(rèn)值為 undefined。

 var vm = new Sun({
      el: '#app',
      data: {
        a: 1
      }
    })

    function Sun(options = {}) {
      this.$options = options; //將實(shí)例中所有的屬性掛載到$options上
      var data = this._data = options.data //將用戶傳過來的data賦值到實(shí)例_data上,并賦值給變量data利于循環(huán)
      obseve(data) //調(diào)用方法,觀察對(duì)象增加Object.defineproperty來設(shè)置值
      for (let key in data) { //遍歷data中對(duì)象,通過object.defineproperty將其賦值到對(duì)象this中
          Object.defineProperty(this,key,{
            enumerable:true,
            get(){
                return  this._data[key]  
            },
            set(newval){
              this._data[key]=newval
            }
          })
      }
    }
    function Observe(data) { 
      for (const key in data) { //將data中的屬性賦值出來,對(duì)其進(jìn)行定義object.defineProperty
        var val = data[key] 
        Object.defineProperty(data, key, {
          enumerable:true,
          get() {
            return val
          },
          set(newval) { //當(dāng)輸入vm._data.a=3 調(diào)用改方法設(shè)置新值
            if (newval == val) {
              return
            }
            val = newval; //把新的值賦值給val,以后取值的時(shí)候get就可以讀到新的值
            obseve(newval) // //進(jìn)行遞歸,深度的數(shù)據(jù)觀察,賦值為對(duì)象時(shí),也要設(shè)置defineproperty
          }
        })
      }
    }


    function obseve(data) { 
      if (typeof data!=='object') return
      return new Observe(data)
    }

【注】在對(duì)象中 . 是和 [ ] 的意思是一樣的。例 sun.name 等價(jià)于 sun[name] , 但是for...in遍歷下標(biāo)中不能混淆, sun[key] 可不等價(jià)與 sun.key 。在 sun[key] 中 key等于 每一次遍歷的 name,age,sex等。 而sun.key 就相當(dāng)于訪問sun對(duì)象的key屬性

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容