Vue中this.$nextTick的作用及用法
Vue實現(xiàn)響應(yīng)式后DOM的變化
data對象中數(shù)據(jù)改變是如何追蹤的?
vue將遍歷data對象中所有的屬性,并通過 Object.defineProperty 把這些屬性全部轉(zhuǎn)為 getter/setter;但是我們是沒有辦法看到 getter/setter的,但是在內(nèi)部它們讓 Vue 能夠追蹤依賴,在屬性被訪問和修改時通知變更。
每個組件都對應(yīng)一個 watcher 實例,它會在組件渲染的過程中把“接觸”過的數(shù)據(jù)屬性記錄為依賴。之后當(dāng)依賴項的 setter 觸發(fā)時,會通知 watcher,從而使它關(guān)聯(lián)的組件重新渲染。
Vue是無法檢測到data對象屬性的添加和刪除
原因:Vue在對初始化組件時會對對象屬性執(zhí)行g(shù)etter/setter轉(zhuǎn)化,所以屬性必須在data對象上存在才能讓Vue將它轉(zhuǎn)化為初始化。
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是響應(yīng)式的
vm.b = 2
// `vm.b` 是非響應(yīng)式的
如何動態(tài)添加根級別的響應(yīng)式屬性【就是對data添加屬性】
this.$set(this.someObject,'b',2)
異步更新隊列
Vue 在更新 DOM 時是異步執(zhí)行的。只要偵聽到數(shù)據(jù)變化,Vue 將開啟一個隊列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更。
如果同一個 watcher 被多次觸發(fā),只會被推入到隊列中一次。這種在緩沖時去除重復(fù)數(shù)據(jù)對于避免不必要的計算和 DOM 操作是非常重要的。
然后,在下一個的事件循環(huán)“tick”中,Vue 刷新隊列并執(zhí)行實際 (已去重的) 工作。
Vue 在內(nèi)部對異步隊列嘗試使用原生的 Promise.then、MutationObserver 和 setImmediate,如果執(zhí)行環(huán)境不支持,則會采用 setTimeout(fn, 0) 代替。
例如,當(dāng)你設(shè)置 vm.someData = 'new value',該組件不會立即重新渲染。
當(dāng)刷新隊列時,組件會在下一個事件循環(huán)“tick”中更新。
多數(shù)情況我們不需要關(guān)心這個過程,但是如果你想基于更新后的 DOM 狀態(tài)來做點什么,這就可能會有些棘手。雖然 Vue.js 通常鼓勵開發(fā)人員使用“數(shù)據(jù)驅(qū)動”的方式思考,避免直接接觸 DOM,但是有時我們必須要這么做。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM,可以在數(shù)據(jù)變化之后立即使用 Vue.nextTick(callback)。這樣回調(diào)函數(shù)將在 DOM 更新完成后被調(diào)用。例如:
<div id="example">{{message}}</div>
var vm = new Vue({
el: '#example',
data: {
message: '123'
}
})
vm.message = 'new message' // 更改數(shù)據(jù)
vm.$el.textContent === 'new message' // false
Vue.nextTick(function () {
vm.$el.textContent === 'new message' // true
})
在組件內(nèi)使用 vm.$nextTick() 實例方法特別方便,因為它不需要全局 Vue,并且回調(diào)函數(shù)中的 this 將自動綁定到當(dāng)前的 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 實現(xiàn)響應(yīng)式并不是數(shù)據(jù)發(fā)生變化之后 DOM 立即變化,而是按一定的策略進(jìn)行 DOM 的更新。
$nextTick 是在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào),在修改數(shù)據(jù)之后使用 $nextTick,則可以在回調(diào)中獲取更新后的 DOM
實例化理解Vue響應(yīng)化
<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;
}
}
})
上例中當(dāng)price 發(fā)生變化的時候,Vue就知道自己需要做三件事情:
- 更新頁面上price的值
- 計算表達(dá)式 price*quantity 的值,更新頁面
- 調(diào)用totalPriceWithTax 函數(shù),更新頁面
數(shù)據(jù)發(fā)生變化后,會重新對頁面渲染,這就是Vue響應(yīng)式,那么這一切是怎么做到的呢?
想完成這個過程,我們需要:
- 偵測數(shù)據(jù)的變化
- 收集視圖依賴了哪些數(shù)據(jù)
- 數(shù)據(jù)變化時,自動“通知”需要更新的視圖部分,并進(jìn)行更新
對應(yīng)專業(yè)俗語分別是:
- 數(shù)據(jù)劫持 / 數(shù)據(jù)代理
- 依賴收集
- 發(fā)布訂閱模式
總結(jié)
再來回顧下整個過程:

在new Vue()后, Vue 會調(diào)用_init函數(shù)進(jìn)行初始化,也就是init 過程,在 這個過程Data通過Observer轉(zhuǎn)換成了getter/setter的形式,來對數(shù)據(jù)追蹤變化,當(dāng)被設(shè)置的對象被讀取的時候會執(zhí)行g(shù)etter函數(shù),而在當(dāng)被賦值的時候會執(zhí)行setter函數(shù)。
當(dāng)外界通過Watcher讀取數(shù)據(jù)時,會觸發(fā)getter從而將Watcher添加到依賴中。
在修改對象的值的時候,會觸發(fā)對應(yīng)的setter,setter通知之前依賴收集得到的 Dep 中的每一個 Watcher,告訴它們自己的值改變了,需要重新渲染視圖。這時候這些 Watcher就會開始調(diào)用update來更新視圖。
以上就是本次介紹的全部相關(guān)知識點內(nèi)容,如果大家學(xué)習(xí)中有任何補充可以聯(lián)系腳本之家小編。
相關(guān)文章
vue監(jiān)聽路由變化時watch方法會執(zhí)行多次的原因及解決
這篇文章主要介紹了vue監(jiān)聽路由變化時watch方法會執(zhí)行多次的原因及解決,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下2021-04-04
Vue初始化中的選項合并之initInternalComponent詳解
這篇文章主要介紹了Vue初始化中的選項合并之initInternalComponent的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Vue3使用Univer Docs創(chuàng)建在線編輯Excel的示例代碼
本文介紹了如何在Vue3項目中集成UniverDocs,一個基于Luckysheet的企業(yè)文檔與數(shù)據(jù)協(xié)同解決方案,指導(dǎo)了從安裝到在頁面中使用的步驟,以及注意事項,如數(shù)據(jù)格式轉(zhuǎn)換和二次開發(fā)的靈活性,需要的朋友可以參考下2025-04-04
解決vue組件銷毀之后計時器繼續(xù)執(zhí)行的問題
這篇文章主要介紹了解決vue組件銷毀之后計時器繼續(xù)執(zhí)行的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-07-07
vue中使用refs定位dom出現(xiàn)undefined的解決方法
本篇文章主要介紹了vue中使用refs定位dom出現(xiàn)undefined的解決方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12

