vue雙向數據綁定原理


一、vue雙向數據綁定原理

vue實現雙向數據綁定是通過Object.defineProperty()方法來實現劫持的
Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象
Object.defineProperty()方法解析
Object.defineProperty()方法有三個參數:
Object.defineProperty(obj, key, options)

參數 功能/作用
obj 要修改或定義key值的對象
key 對應obj對象的里面某有已有或要修改的屬性
options 這個參數對象里面有get,set兩個函數,用來定義屬性值

options有兩種主要形式:數據描述符和存取描述符
數據描述符是一個具有值的屬性,該值可能是可寫的,也可能不是可寫的
存取描述符是由getter-setter函數對描述的屬性
描述符必須是這兩種形式之一;不能同時是兩者
options參數配置:
數據描述符和存取描述符均具有以下可選鍵值

{
    configurable: Boolean, // 當且僅當該屬性的 configurable 為 true 時,該屬性描述符才能夠被改變,同時該屬性也能從對應的對象上被刪除,默認為 false
    enumerable: Boolean, // 當且僅當該屬性的enumerable為true時,該屬性才能夠出現在對象的枚舉屬性中

}

數據描述符同時具有以下可選鍵值

{
    value: undefined, // 該屬性對應的值。可以是任何有效的 JavaScript 值(數值,對象,函數等)。默認為 undefined
    writable: Boolean, // 當且僅當該屬性的writable為true時,value才能被賦值運算符改變。默認為 false
}

存取描述符同時具有以下可選鍵值:默認值:undefined

{
    get: fn, // 一個給屬性提供 getter 的方法,如果沒有 getter 則為 undefined。當訪問該屬性時,該方法會被執行,方法執行時沒有參數傳入,但是會傳入this對象(由於繼承關系,這里的this並不一定是定義該屬性的對象),這個方法沒有參數
    set: fn, // 一個給屬性提供 setter 的方法,如果沒有 setter 則為 undefined。當屬性值修改時,觸發執行該方法。該方法有一個參數,就是對應的每次修改的新值
}

二、模擬測試

let Test = {
    name: 1
}

console.log(Test.name) // 1

如果我現在想要讓1,輸出true,0輸出false,怎么辦?我們可以通過Object.defineProperty()方法實現

let Test = {}
  let name = ''
  Object.defineProperty(Test, 'name', {
    configurable: true,
    enumerable: true,
    set: function (val) {
      name = val
      console.log('你輸入的值為:' + val)
    },
    get: function () {
      if (name === 1) {
        name = true
        console.log('獲取值的時候觸發!')
        return name
      } else if (name === 0) {
        name = false
        console.log('獲取值的時候觸發!')
        return name
      }
    }
  })

分別測試一下結果:

Test.name = 0  => // 當我們改變對象或者為對象添加一個屬性時,觸發了set函數:你輸入的值為:0
console.log(Test.name) => // false
console.log(name) => // false

// 通過測試改變Test對象的屬性,我們發現不僅Test對象里面改變了,而且name變量也改變了
name = 0 => // 我們發現,我們改變了name變量的值,但是並沒有觸發set函數,(可以理解為set只能觸發對象參數里面的改變)
console.log(Test.name) => // false
console.log(name) => // false

// 通過測試改變了name變量的值,發現兵沒有觸發set函數,但是Test對象和name變量的值還是跟着改變了,只觸發了get函數,相當於獲取name值

PS:這里是補充的,上面的測試依舊可以試下,但是原理和結論並不是那樣的,其實Object.defineProperty()方法可以理解為監聽的就是Test這個對象的,name就是添加的或對象已有的一個屬性,這就是為什么上面單獨改變name屬性,並沒有觸發set函數,當我們改變Test對象的name屬性時,set獲取新值,並將其重新賦值給name變量,並在get函數里返回,這樣就可以實現動態改變Test的name屬性值來保持Test.name===name,所以我們只能操作Test.name,如果要操作name,還是要賦值給Test.name,間接操作Texst.name,然后觸發后續事件
這里結合vue的雙向綁定只能在input,checkbox這些標簽上使用,可以理解為這些標簽的value的屬性值就相當於我們測試的name屬性,通過value可以時刻動態監聽input等標簽value值的變化,然后將這個新value值賦值給對象指定屬性,然后就可以觸發后續函數。

三、簡單粗暴的雙向綁定

<div id="demo"></div> // 這個是用來動態顯示input標簽里面的value值的
<input type="text" id="inp" /> // 通過監聽input標簽的value值,賦值給我們監聽的對象屬性
let Obj = {} => // 監聽對象
  let demo = document.getElementById('demo') // 獲取DOM
  let inp = document.getElementById('inp') // 獲取DOM
  Object.defineProperty(Obj, 'text', {
    configurable: true,
    enumerable: true,
    set: function (val) {
      // 將Obj對象新改變的值賦值給input的value,然后頁賦值給demo
      inp.value = val
      demo.innerHTML = val
      console.log('input里面輸入了' + val)
    },
    get: function () {
       // 返回對象
      return Obj
    }
  })

測試結果:
無論是在input標簽里面輸入,還是改變Obj.text的值,兩者都會同時改變
至此,vue雙向數據綁定原理挖坑完畢。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM