標籤:轉換 也有 ima 不必要 mis this 嵌套 對象 一個
工作的過程中,有時候會有資料改變但是視圖沒有更新的問題,作者在vue的官方文檔中有提到這個問題,我來總結一下
1.vue的每個組件執行個體都有對象的watcher執行個體對象,它會在組件渲染的過程中把屬性記錄為依賴,當依賴項的setter方法被調用,會通知watcher對象重新計算,從而使它關聯的組件更新
檢測變化的注意項,vue不能檢測到對象屬性的添加或者刪除,由於 Vue 會在初始化執行個體時對屬性執行 getter/setter 轉化過程,所以屬性必須在 data 對象上存在才能讓 Vue 轉換它,這樣才能讓它是響應的
2.Vue 不允許在已經建立的執行個體上動態添加新的根級響應式屬性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法將響應屬性添加到嵌套的對象上:
Vue.set(vm.someObject, ‘b‘, 2)// 或者this.$set(this.someObject,‘b‘,2)
有時你想向一個已有對象添加多個屬性,例如使用 Object.assign() 或 _.extend() 方法來添加屬性。但是,這樣添加到對象上的新屬性不會觸發更新。在這種情況下可以建立一個新的對象,讓它包含原對象的屬性和新的屬性:
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`this.someObject = Object.assign({}, this.someObject, {a: 1, b: 2 })
3.聲明響應式屬性
由於 Vue 不允許動態添加根級響應式屬性,所以你必須在初始化執行個體前聲明根級響應式屬性,哪怕只是一個空值:
var vm = new Vue({ data: { // 聲明 message 為一個空值字串 message: ‘‘ }, template: ‘<div>{{ message }}</div>‘})// 之後設定 `message`vm.message = ‘Hello!‘
如果你未在 data 選項中聲明 message,Vue 將警告你渲染函數正在試圖訪問的屬性不存在。
這樣的限制在背後是有其技術原因的,它消除了在依賴項跟蹤系統中的一類邊界情況,也使 Vue 執行個體在類型檢查系統的協助下啟動並執行更高效。而且在代碼可維護性方面也有一點重要的考慮:data 對象就像組件狀態的概要,提前聲明所有的響應式屬性,可以讓組件代碼在以後重新閱讀或其他開發人員閱讀時更易於被理解。
4.非同步更新隊列(重點理解)
Vue 非同步執行 DOM 更新。只要觀察到資料變化,Vue 將開啟一個隊列,並緩衝在同一事件迴圈中發生的所有資料改變。如果同一個 watcher 被多次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複資料對於避免不必要的計算和 DOM 操作上非常重要。然後,在下一個的事件迴圈“tick”中,Vue 重新整理隊列並執行實際 (已去重的) 工作。Vue 在內部嘗試對非同步隊列使用原生的 Promise.then 和 MessageChannel,如果執行環境不支援,會採用 setTimeout(fn, 0) 代替
當你設定 vm.someData = ‘new value‘ ,該組件不會立即重新渲染。當重新整理隊列時,組件會在事件迴圈隊列清空時的下一個“tick”更新。多數情況我們不需要關心這個過程,但是如果你想在 DOM 狀態更新後做點什麼,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發人員沿著“資料驅動”的方式思考,避免直接接觸 DOM,但是有時我們確實要這麼做。為了在資料變化之後等待 Vue 完成更新 DOM ,可以在資料變化之後立即使用 Vue.nextTick(callback) 。這樣回呼函數在 DOM 更新完成後就會調用。例如:
var vm = new Vue({ el: ‘#example‘, data: { message: ‘123‘ }})vm.message = ‘new message‘ // 更改資料vm.$el.textContent === ‘new message‘ // falseVue.nextTick(function () { vm.$el.textContent === ‘new message‘ // true})
深入Vue的響應式原理