­

vue2雙向綁定原理:深入響應式原理defineProperty、watcher、get、set

響應式是什麼?Vue 最獨特的特性之一~

就是我們在頁面開發時,修改data值的時候,數據、視圖頁面需要變化的地方變化。

主要使用到哪些方法?

用 Object.defineProperty給watcher對象的每一個屬性分別定義了get和set。getter負責記錄依賴,setter負責數據攔截、對data屬性的賦值和修改dom更新。大白話就是通過數據劫持 defineProperty + 發佈訂閱者模式。

深入講解

官方原文

一個普通的 JavaScript 對象傳入 Vue 實例作為 data 選項,Vue 將遍歷此對象所有的 property,並使用 Object.defineProperty 把這些 property 全部轉為 getter/setter。 

這些 getter/setter 對用戶來說是不可見的,但是在內部它們讓 Vue 能夠追蹤依賴,在 property 被訪問和修改時通知變更。這裡需要注意的是不同瀏覽器在控制台打印數據對象時對 getter/setter 的格式化並不同,所以建議安裝 vue-devtools 來獲取對檢查數據更加友好的用戶界面。

每個組件實例都對應一個 watcher 實例,它會在組件渲染的過程中把「接觸」過的數據 property 記錄為依賴。之後當依賴項的 setter 觸發時,會通知 watcher,從而使它關聯的組件重新渲染。

 實現一個『簡易版雙向綁定』

 1.創建一個data對象,頁面為空白,defineProperty綁定data.a。

<div id="app">
   <!-- 顯示data.a的值 -->
//{{data.a}}
  //app依賴於data中的a
</div>
<script>
    const data={a:1}
    //在vue中每一個data屬性都有一個Object.defineProperty
    Object.defineProperty(data,'a',{
      get:function(){
        console.log(`訪問a`);
      },
      set:function(value){
        document.getElementById('app').innerHTML=value
     } 
})

</script>

2.測試效果

在頁面訪問data值,會實時展示。當有人訪問到了a屬性就會觸發get這個函數。

 

在頁面修改data值,頁面會實時展示。當有人給a進行賦值的時候就會觸發set這個函數。

data.a=10

頁面

 

 這時視圖發生變化,符合Vue雙向數據綁定的原理,即:數據=>視圖,也可以的到的是set裏面value的值是輸入的10。

缺陷

  1. 在ES5中無法shim:Object.defineProperty 是 ES5 中一個無法 shim 的特性,這也就是 Vue 不支持 IE8 以及更低版本瀏覽器的原因。(shim:可以將新的API引入到舊的環境中,而且僅靠就環境中已有的手段實現);
  2. 由於 JavaScript 的限制,Vue 不能檢測數組和對象的變化:
    • object.defineproperty 無法監控到數組下標的變化,導致通過數組下標添加元素,無法實時響應;
    • object.defineProperty 只能劫持對象的屬性,從而需要對每個對象,每個屬性進行遍歷,如果,屬性值是對象,還需要深度遍歷。
Tags: