VUE是如何追蹤變化的
當你把一個普通的 JavaScript 對象傳入 Vue 實例做爲 data 選項,Vue 將遍歷此對象全部的 property,並使用 Object.defineProperty 把這些 property 所有轉爲 getter/setter。Object.defineProperty 是 ES5 中一個沒法 shim 的特性,這也就是 Vue 不支持 IE8 以及更低版本瀏覽器的緣由。
每一個組件實例都對應一個 watcher 實例,它會在組件渲染的過程當中把「接觸」過的數據 property 記錄爲依賴。以後當依賴項的 setter 觸發時,會通知 watcher,從而使它關聯的組件從新渲染。
檢測變化的注意事項
因爲 JavaScript 的限制,Vue 不能檢測數組和對象的變化。儘管如此咱們仍是有一些辦法來回避這些限制並保證它們的響應性。
對於對象
對於已經建立的實例,Vue 不容許動態添加根級別的響應式 property。可是,可使用 Vue.set(object, propertyName, value) 方法向嵌套對象添加響應式 property。例如,對於
Vue.set(vm.someObject, 'b', 2)
您還可使用 vm.$set 實例方法,這也是全局 Vue.set 方法的別名:
this.$set(this.someObject,'b',2)
有時你可能須要爲已有對象賦值多個新 property,好比使用 Object.assign() 或 _.extend()。可是,這樣添加到對象上的新 property 不會觸發更新。在這種狀況下,你應該用原對象與要混合進去的對象的 property 一塊兒建立一個新的對象。
對於數組
Vue 不能檢測如下數組的變更:
- 當你利用索引直接設置一個數組項時,例如:vm.items[indexOfItem] = newValue
- 當你修改數組的長度時,例如:vm.items.length = newLength
爲了解決第一類問題,如下兩種方式均可以實現和 vm.items[indexOfItem] = newValue 相同的效果,同時也將在響應式系統內觸發狀態更新:
// Vue.set
Vue.set(vm.items, indexOfItem, newValue
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
聲明響應式 property
因爲 Vue 不容許動態添加根級響應式 property,因此你必須在初始化實例前聲明全部根級響應式 property,哪怕只是一個空值:
若是你未在 data 選項中聲明 message,Vue 將警告你渲染函數正在試圖訪問不存在的 property。
這樣的限制在背後是有其技術緣由的,它消除了在依賴項跟蹤系統中的一類邊界狀況,也使 Vue 實例能更好地配合類型檢查系統工做。
但與此同時在代碼可維護性方面也有一點重要的考慮:data 對象就像組件狀態的結構 (schema)。提早聲明全部的響應式 property,可讓組件代碼在將來修改或給其餘開發人員閱讀時更易於理解。
異步更新隊列
例如,當你設置 vm.someData = 'new value',該組件不會當即從新渲染。當刷新隊列時,組件會在下一個事件循環「tick」中更新。多數狀況咱們不須要關心這個過程,可是若是你想基於更新後的 DOM 狀態來作點什麼,這就可能會有些棘手。雖然 Vue.js 一般鼓勵開發人員使用「數據驅動」的方式思考,避免直接接觸 DOM,可是有時咱們必需要這麼作。爲了在數據變化以後等待 Vue 完成更新 DOM,能夠在數據變化以後當即使用 Vue.nextTick(callback)。這樣回調函數將在 DOM 更新完成後被調用。