就是我們在頁面開發時,修改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。
在ES5中無法shim:Object.defineProperty
是 ES5 中一個無法 shim 的特性,這也就是 Vue 不支援 IE8 以及更低版本瀏覽器的原因。(shim:可以將新的API引入到舊的環境中,而且僅靠就環境中已有的手段實現);