Vue雙向數據綁定


一、引入

  談及Vue中的數據雙向綁定,我們自然而然的想到是通過v-model指令實現的。但具體是怎么實現的呢?下面就介紹一下。

 

二、v-model語法糖是什么?原理是什么?

  v-model語法糖是vue多個基礎語法(屬性綁定 和事件綁定)的簡寫。

  原理:給表單元素input綁定通過"v-bind:"綁定value屬性的數據msg,再給表單元素input添加監聽value值改變的事件@input,給msg重新賦值。

  代碼:

<!-- <input type="text" v-model="msg"> -->
<input :value="msg" type="text" @input="msg=$event.target.value">

 

三、雙向數據綁定的原理?

  vue中數據雙向綁定通過v-model實現,雙向綁定指的是視圖和內存中的數據進行雙向綁定。(通過Object.defineProperty和給元素注冊事件)

  表單元素改變數據的原理:

  • 實現數據驅動視圖
  1. 需要先定義一個data對象將其中msg屬性的值顯示到視圖中。想要通過Object.defineProperty來監測其值得變化是不可能實現的,因為使用他的同時需要給對象賦值並監聽,而data對象中已經有了這個屬性並綁定到了頁面中顯示,無法再重新定義該屬性。這就需要新建一個空對象vm,通過給vm定義屬性並監測來實現這個功能。
  2. Object.defineProperty調用時的第三個參數為對象配置項,其中的get()方法為vm的msg屬性值被獲取時觸發的回調函數。set()方法為vm的msg屬性值被設置時觸發的回調函數,set()函數的參數為msg屬性的新值。
  • 實現視圖驅動數據

  通過給表單元素注冊input事件,將表單元素中的value值賦給vue.msg

 <!-- 1. 把數據渲染到表單元素中 -->
  <!-- 2. 當你修改數據的時候,表單元素的值發生改變,視圖需要更新 -->
  <!-- 3. 當你使用表單元素的時候,你在修改元素的值,對應的數據也要發生改變 -->
  <h5></h5>
  <input type="text">
  <script>
    // const vm = new Vue({data:{msg:'hi vue'}}) vm.msg = '數據'
    // 使用用定義可以監聽(觀察)的屬性的。
    const vm = {}
    const data = { msg: 'hi vue' }
    // 獲取dom
    const h5 = document.querySelector('h5')
    const input = document.querySelector('input')
    // 1. 默認渲染
    h5.innerHTML = data.msg
    input.value = data.msg
    // 2.1 監聽 data中的msg的值改變  觀察 data中的msg的值改變  最終監聽的是vm的msg屬性變化
    // 2.2 如果 數據改變  修改視圖
    // 三個參數  給誰定義一個屬性  屬性的名稱  對象配置項(get 獲取屬性值 set 設置屬性值)
    Object.defineProperty(vm, 'msg', {
      get() {
        // 當獲取msg屬性值時觸發
        // console.log('get')
        return data['msg']
      },
      set(newValue) {
        // 當設置msg屬性值時觸發
        // console.log('set')
        // console.log(newValue)
        // 數據改變
        data['msg'] = newValue
        // 修改視圖
        h5.innerHTML = newValue
        input.value = newValue
      }
    })
    // 3. 監聽 表單元素 的值改變事件  修改數據即可(上面已經實現數據驅動視圖)
    input.oninput = function(){
      // console.log(this.value)
      vm.msg = this.value
    }
  </script>

  總體描述:

  • Vue內部會把data中的數據通過defineProperty方法轉化為set和get的監控方式

  • 當data中的數據發生變化時,會觸發對應的set或者get

    • 修改屬性值的時候,觸發set方法

    • 訪問屬性值的時候,觸發get方法

  • 監控數據變化的目的還是為了更新頁面(僅僅更新數據變化對應的DOM節點:盡可能少的更新DOM)

  • 但是完成上述要求需要底層虛擬DOM的支持

 

四、什么是虛擬DOM?

  瀏覽器更新DOM比較耗時,為了節省時間,需要盡可能少的更新DOM。虛擬DOM是對真實DOM的一種描述;其組成部分虛擬節點也描述了真實的DOM節點,本質上就是普通對象

// VNODE 虛擬節點:描述了真實的DOM節點,本質上就是普通對象
{
    tagName: 'div'
    attrs: { class: "active", id: "info"}
    content: "hello"
}
  • 虛擬DOM也會形成一個樹狀結構,描述了真實的DOM樹(形成虛擬DOM樹和真實DOM樹的對應關系)

  • 如果數據發生變化,那么就會觸發虛擬DOM數的對比(diff算法,過程發生在內存中)

  • 對比的結果是:有變化的虛擬節點的集合

  • 上述虛擬節點需要轉化為真實的DOM節點(下面是虛擬下面是虛擬節點轉換為真實節點的過程)

var div = document.createElement(vnode.tagName)
div.setAttibute(key, value)
div.innerHTML = vnode.content
  • 最終會把真實的節點更新到頁面

  雙向數據綁定運用虛擬DOM的進一步解釋說明:

    在使用defineProperty進行到set()時,會采用虛擬DOM來跟新視圖;虛擬DOM有新、舊兩份數據存儲在內存中,每次監測到數據改變時,計算機會通過diff算法對比兩份數據的區別,得到有變化的虛擬節點的集合,並將它們轉換為真實的DOM節點更新到頁面中。

    采用上面方式的原因就是瀏覽器解析完整DOM樹的時間、性能消耗,要遠比內存對比數據再進行局部渲染的消耗大得多。內存處理數據的速度要比瀏覽器快的多。

 


免責聲明!

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



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