Vue 最獨特的特性之一,是其非侵入性的響應式系統。數據模型僅僅是普通的 JavaScript 對象。而當你修改它們時,視圖會進行更新。這使得狀態管理很是簡單直接vue
你們都知道vue的響應式原理是經過ES6新增的屬性Object.defineProperty來實現的,在說vue響應式原理以前不得不先說一下Object.defineProperty這個方法react
(Object.defineProperty 是 ES5 中一個沒法 shim 的特性,這也就是爲何 Vue 不支持 IE8 以及更低版本瀏覽器。)git
vue實現雙向數據綁定的原理就是利用了 Object.defineProperty() 這個方法從新定義了對象獲取屬性值(get)和設置屬性值(set)的操做來實現的。github
在MDN上對該方法的說明是:算法
Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 並返回這個對象。瀏覽器
---它接收三個參數,要操做的對象,要定義或修改的對象屬性名,屬性描述符。異步
--- 重點就是最後的屬性描述符。async
屬性描述符是一個對象,主要有兩種形式:數據描述符和存取描述符。ide
這兩種形式只能選擇一種使用,不能混合兩種描述符的屬性同時使用。上面說的get和set就是屬於存取描述符對象的屬性。函數
而後咱們能夠經過在存取描述符中的get和set方法內寫入自定義的邏輯來實現對象獲取屬性和設置屬性時的行爲。
說完了Object.defineProperty() 這個方法,那麼就來講一下vue是如何實現響應式的吧
對於上圖,個人理解是
組件、函數等渲染---->建立一個虛擬DOM樹------->當data、computed、props改變時會引發頁面的刷新--------watcher檢測變化,當變化之後不會當即渲染,會有一個隊列,只要觀察到數據變化,Vue 將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據改變。若是同一個 watcher 被屢次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做上很是重要。而後,在下一個的事件循環「tick」中,Vue 刷新隊列並執行實際 (已去重的) 工做。
在這兒有一個虛擬DOM的概念
虛擬DOM是一個特別棒的概念,咱們都知道,在瀏覽器上進行DOM操做的時候,會特別的消耗性能並且響應特別慢,可是有了虛擬DOM就不同了,
在這兒不得不說一下虛擬DOM了,虛擬DOM就是將DOM樹轉換成一個JS對象樹,
虛擬DOM就是將上述的標籤寫成一個js對象樹,以下
當DOM改變的時候,他會使用Diff算法將改變之後的js對象樹與原先的js對象樹進行比較,這個比較是逐層比較的,當發現節點刪除就刪除,增長就增長,
可是因爲他是一級一級進行比較的,這樣就會有一個致命的缺點:假設在根元素上又嵌套了一個元素,那麼就至關於從新建立了一個JS對象樹,這樣效率仍是不高,還有一個致命i
的缺點就是;若是同一級上有特別多個相同的元素,就會在循環比較的時候浪費掉大量的性能
因而,爲了解決這兩個缺點,虛擬DOM作了兩個假設,而且這兩個假設也實現了,因此已經解決了這兩個缺點
兩個假設:
一、兩個相同的組件產生相似的DOM結構,不一樣的DOM節點產生不一樣的DOM節點
二、對於同一個層次的一組節點,他們能夠經過惟一的id進行區分
對於第二種假設,就是解釋了咱們爲何要在vue的v-for裏面必須加一個key 而且這個key要是惟一的
當你把一個普通的 JavaScript 對象傳給 Vue 實例的 data
選項,Vue 將遍歷此對象全部的屬性,並使用 Object.defineProperty 把這些屬性所有轉爲 getter/setter。
這些 getter/setter 對用戶來講是不可見的,可是在內部它們讓 Vue 追蹤依賴,在屬性被訪問和修改時通知變化。這裏須要注意的問題是瀏覽器控制檯在打印數據對象時 getter/setter 的格式化並不一樣,因此你可能須要安裝 vue-devtools 來獲取更加友好的檢查接口。
每一個組件實例都有相應的 watcher 實例對象,它會在組件渲染的過程當中把屬性記錄爲依賴,以後當依賴項的 setter
被調用時,會通知 watcher
從新計算,從而導致它關聯的組件得以更新。
Vue 不能檢測到對象屬性的添加或刪除。
因爲 Vue 會在初始化實例時對屬性執行 getter/setter
轉化過程,因此屬性必須在 data
對象上存在才能讓 Vue 轉換它,這樣才能讓它是響應的。
Vue 不容許在已經建立的實例上動態添加新的根級響應式屬性 (root-level reactive property)。然而它可使用 Vue.set(object, key, value)
方法將響應屬性添加到嵌套的對象上
Vue.set(vm.someObject, 'b', 2)或者this.$set(this.someObject,'b',2)
對象添加多個屬性時
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
vue中DOM的更新是一個異步操做,DOM修改後不會當即刷新頁面
Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue 將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據改變。若是同一個 watcher 被屢次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做上很是重要。而後,在下一個的事件循環「tick」中,Vue 刷新隊列並執行實際 (已去重的) 工做。
並且vue檢測DOM樹的變化是一級一級的對比的,o1 ,速度快
在組件內使用 vm.$nextTick()
實例方法特別方便,由於它不須要全局 Vue
,而且回調函數中的 this
將自動綁定到當前的 Vue 實例上。$nextTick()
返回一個 Promise 對象,因此你可使用新的 ES6 async/await語法完成相同的事情
若是本文對您有幫助,請擡擡您的小手,點下右下角的推薦, ^-^,固然若是看了這篇博客對您有幫助是我最開心的事,畢竟贈人玫瑰,手有餘香, ^-^,若是這篇博客沒有幫助到您,那就只能說一聲抱歉啦