Vue中this.$nextTick的作用及用法
Vue實現響應式後DOM的變化
data物件中資料改變是如何追蹤的?
vue將遍歷data物件中所有的屬性,並通過 Object.defineProperty 把這些屬性全部轉為 getter/setter;但是我們是沒有辦法看到 getter/setter的,但是在內部它們讓 Vue 能夠追蹤依賴,在屬性被訪問和修改時通知變更。
每個元件都對應一個 watcher 例項,它會在元件渲染的過程中把“接觸”過的資料屬性記錄為依賴。之後當依賴項的 setter 觸發時,會通知 watcher,從而使它關聯的元件重新渲染。
Vue是無法檢測到data物件屬性的新增和刪除
原因:Vue在對初始化元件時會對物件屬性執行getter/setter轉化,所以屬性必須在data物件上存在才能讓Vue將它轉化為初始化。
var vm = new Vue({ data:{ a:1 } }) // `vm.a` 是響應式的 vm.b = 2 // `vm.b` 是非響應式的
如何動態新增根級別的響應式屬性【就是對data新增屬性】
this.$set(this.someObject,'b',2)
非同步更新佇列
Vue 在更新 DOM 時是非同步執行的。只要偵聽到資料變化,Vue 將開啟一個佇列,並緩衝在同一事件迴圈中發生的所有資料變更。
如果同一個 watcher 被多次觸發,只會被推入到佇列中一次。這種在緩衝時去除重複資料對於避免不必要的計算和 DOM 操作是非常重要的。
然後,在下一個的事件迴圈“tick”中,Vue 重新整理佇列並執行實際 (已去重的) 工作。
Vue 在內部對非同步佇列嘗試使用原生的 Promise.then、MutationObserver 和 setImmediate,如果執行環境不支援,則會採用 setTimeout(fn,0) 代替。
例如,當你設定 vm.someData = 'new value',該元件不會立即重新渲染。
當重新整理佇列時,元件會在下一個事件迴圈“tick”中更新。
多數情況我們不需要關心這個過程,但是如果你想基於更新後的 DOM 狀態來做點什麼,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發人員使用“資料驅動”的方式思考,避免直接接觸 DOM,但是有時我們必須要這麼做。為了在資料變化之後等待 Vue 完成更新 DOM,可以在資料變化之後立即使用 Vue.nextTick(callback)。這樣回撥函式將在 DOM 更新完成後被呼叫。例如:
<div id="example">{{message}}</div> var vm = new Vue({ el: '#example',data: { message: '123' } }) vm.message = 'new message' // 更改資料 vm.$el.textContent === 'new message' // false Vue.nextTick(function () { vm.$el.textContent === 'new message' // true })
在元件內使用 vm.$nextTick() 例項方法特別方便,因為它不需要全域性 Vue,並且回撥函式中的 this 將自動繫結到當前的 Vue 例項上:
Vue.component('example',{ template: '<span>{{ message }}</span>',data: function () { return { message: '未更新' } },methods: { updateMessage: function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' this.$nextTick(function () { console.log(this.$el.textContent) // => '已更新' }) } } })
因為 $nextTick() 返回一個 Promise 物件,所以你可以使用新的 ES2017 async/await 語法完成相同的事情:
methods: { updateMessage: async function () { this.message = '已更新' console.log(this.$el.textContent) // => '未更新' await this.$nextTick() console.log(this.$el.textContent) // => '已更新' } }
Vue 實現響應式並不是資料發生變化之後 DOM 立即變化,而是按一定的策略進行 DOM 的更新。
$nextTick 是在下次 DOM 更新迴圈結束之後執行延遲迴調,在修改資料之後使用 $nextTick,則可以在回撥中獲取更新後的 DOM
例項化理解Vue響應化
<div id="app"> <div>Price :¥{{ price }}</div> <div>Total:¥{{ price * quantity }}</div> <div>Taxes: ¥{{ totalPriceWithTax }}</div> <button @click="changePrice">改變價格</button> </div> var app = new Vue({ el: '#app',data() { return { price: 5.0,quantity: 2 }; },computed: { totalPriceWithTax() { return this.price * this.quantity * 1.03; } },methods: { changePrice() { this.price = 10; } } })
上例中當price 發生變化的時候,Vue就知道自己需要做三件事情:
- 更新頁面上price的值
- 計算表示式 price*quantity 的值,更新頁面
- 呼叫totalPriceWithTax 函式,更新頁面
資料發生變化後,會重新對頁面渲染,這就是Vue響應式,那麼這一切是怎麼做到的呢?
想完成這個過程,我們需要:
- 偵測資料的變化
- 收集檢視依賴了哪些資料
- 資料變化時,自動“通知”需要更新的檢視部分,並進行更新
對應專業俗語分別是:
- 資料劫持 / 資料代理
- 依賴收集
- 釋出訂閱模式
總結
再來回顧下整個過程:
在new Vue()後, Vue 會呼叫_init函式進行初始化,也就是init 過程,在 這個過程Data通過Observer轉換成了getter/setter的形式,來對資料追蹤變化,當被設定的物件被讀取的時候會執行getter函式,而在當被賦值的時候會執行setter函式。
當外界通過Watcher讀取資料時,會觸發getter從而將Watcher新增到依賴中。
在修改物件的值的時候,會觸發對應的setter,setter通知之前依賴收集得到的 Dep 中的每一個 Watcher,告訴它們自己的值改變了,需要重新渲染檢視。這時候這些 Watcher就會開始呼叫update來更新檢視。
以上就是本次介紹的全部相關知識點內容,如果大家學習中有任何補充可以聯絡我們小編。