一是己、$nextTick的定義及理解:
定義:在下次 DOM 更新循環(huán)結(jié)束之后執(zhí)行延遲回調(diào)。在修改數(shù)據(jù)之后立即使用這個方法任柜,獲取更新后的 DOM赃泡。
所以就衍生出了這個獲取更新后的DOM的Vue方法寒波。所以放在Vue.nextTick()回調(diào)函數(shù)中的執(zhí)行的應(yīng)該是會對DOM進(jìn)行操作的 js代碼乘盼;
理解:nextTick()升熊,是將回調(diào)函數(shù)延遲在下一次dom更新數(shù)據(jù)后調(diào)用,簡單的理解是:當(dāng)數(shù)據(jù)更新了绸栅,在dom中渲染后级野,自動執(zhí)行該函數(shù),
Vue.nextTick()是vue的全局api粹胯,它主要用來在下次dom更新循環(huán)結(jié)束之后執(zhí)性延遲回調(diào)蓖柔。在修改數(shù)據(jù)之后立即使用這個方法,獲取更新后的dom
由于vue的更新機(jī)制是異步的风纠,所以當(dāng)數(shù)據(jù)修改之后况鸣,dom還停留在更新之前,此時想要獲取更新之后的dom竹观,可以使用 nextTick镐捧,表示的是下次dom更新循環(huán)結(jié)束后執(zhí)行的回調(diào)。
應(yīng)用場景:created中獲取dom可以使用nextTick
二臭增、$nextTick(callback) 使用原理:
Vue是異步執(zhí)行dom更新的懂酱,一旦觀察到數(shù)據(jù)變化,Vue就會開啟一個隊(duì)列誊抛,然后把在同一個事件循環(huán) (event loop) 當(dāng)中觀察到數(shù)據(jù)變化的 watcher 推送進(jìn)這個隊(duì)列列牺。如果這個watcher被觸發(fā)多次,只會被推送到隊(duì)列一次拗窃。這種緩沖行為可以有效的去掉重復(fù)數(shù)據(jù)造成的不必要的計(jì)算和DOm操作瞎领。而在下一個事件循環(huán)時,Vue會清空隊(duì)列随夸,并進(jìn)行必要的DOM更新九默。
當(dāng)你設(shè)置 改變了一個新數(shù)據(jù)data,DOM 并不會馬上更新逃魄,而是在異步隊(duì)列被清除荤西,也就是下一個事件循環(huán)開始時執(zhí)行更新時才會進(jìn)行必要的DOM更新。如果此時你想要根據(jù)更新的 DOM 狀態(tài)去做某些事情伍俘,就會出現(xiàn)問題邪锌。。為了在數(shù)據(jù)變化之后等待 Vue 完成更新 DOM 癌瘾,可以在數(shù)據(jù)變化之后立即使用 vue.nextTick(callback) 觅丰。這樣回調(diào)函數(shù)在 DOM 更新完成后就會調(diào)用。
三妨退、什么時候需要用的this.nextTick() 妇萄?
Vue生命周期的created()鉤子函數(shù)進(jìn)行的DOM操作一定要放在Vue.nextTick()的回調(diào)函數(shù)中蜕企,原因是在created()鉤子函數(shù)執(zhí)行的時候DOM 其實(shí)并未進(jìn)行任何渲染,而此時進(jìn)行DOM操作無異于徒勞冠句,所以此處一定要將DOM操作的js代碼放進(jìn)Vue.nextTick()的回調(diào)函數(shù)中轻掩。與之對應(yīng)的就是mounted鉤子函數(shù),因?yàn)樵撱^子函數(shù)執(zhí)行時所有的DOM掛載已完成懦底。
當(dāng)項(xiàng)目中你想在改變DOM元素的數(shù)據(jù)后基于新的dom做點(diǎn)什么唇牧,對新DOM一系列的js操作都需要放進(jìn)Vue.nextTick()的回調(diào)函數(shù)中;通俗的理解是:更改數(shù)據(jù)后當(dāng)你想立即使用js操作新的視圖的時候需要使用它
四聚唐、列舉兩種使用場景
1丐重、有一個div,默認(rèn)用v-if將它隱藏杆查,點(diǎn)擊一個按鈕后扮惦,改變v-if的值,讓它顯示出來亲桦,同時拿到這個div的文本內(nèi)容崖蜜。如果v-if的值是false,直接去獲取div的內(nèi)容是獲取不到的烙肺,因?yàn)榇藭rdiv還沒有被創(chuàng)建出阿里纳猪,那么應(yīng)該在點(diǎn)擊按鈕后,改變v-if的值為true桃笙,div才會被創(chuàng)建氏堤,此時再去獲取。
<template lang="html">
<div id="app">
<div id="divBox" v-if="showText">測試文本內(nèi)容</div>
<button @click="getText">獲取div內(nèi)容</button>
</div>
</template>
<script>
export default {
data () {
return {
showText: false
}
},
mounted () {
},
methods: {
getText () {
this.showText = true;
var innerHTML = document.getElementById('divBox').innerHTML;
console.log(innerHTML);
}
},
}
</script>
<style lang="less">
</style>
運(yùn)行后會拋出一個錯誤:Cannot read property “innerHTML” of null搏明,意思就是獲取不到div元素鼠锈。這里涉及Vue一個重要的概念:異步更新隊(duì)列。
Vue在觀察到數(shù)據(jù)變化時并不是直接更新DOM星著,而是開啟一個隊(duì)列购笆,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)改變。在緩沖時會去除重復(fù)數(shù)據(jù)虚循,從而避免不必要的計(jì)算和DOM操作同欠。然后再下一個事件循環(huán)tick中,Vue刷新隊(duì)列并執(zhí)行實(shí)際(已去重的)工作横缔。所以如果用一個for循環(huán)來動態(tài)改變數(shù)據(jù)100次铺遂,其實(shí)它只會應(yīng)用最后一次改變,如果沒有這種機(jī)制茎刚,DOM就要重繪100次襟锐,過于耗費(fèi)資源。
Vue會根據(jù)當(dāng)前瀏覽器環(huán)境優(yōu)先使用原生的Promise.then和MutationObserver膛锭,如果都不支持粮坞,就會采用setTimeout代替蚊荣。
事實(shí)上,在執(zhí)行this.showText= true莫杈;時互例,div仍然還是沒有被創(chuàng)建出來,直到下一個Vue事件循環(huán)時姓迅,才開始創(chuàng)建敲霍。 $nextTick就是用來指導(dǎo)什么時候DOM更新完成的,所以上面的示例需要改寫為:
<template lang="html">
<div id="app">
<div id="divBox" v-if="showText">測試文本內(nèi)容</div>
<button @click="getText">獲取div內(nèi)容</button>
</div>
</template>
<script>
export default {
data () {
return {
showText: false
}
},
mounted () {
},
methods: {
getText () {
this.showText = true;
this.$nextTick(() => {
var innerHTML = document.getElementById('divBox').innerHTML;
console.log(innerHTML);
})
}
},
}
</script>
<style lang="less">
</style>
2丁存、修改內(nèi)容
<template>
<div>
<button id="btn" @click="testClick()" ref="test">{{testMsg}}</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
testMsg: "oldValue",
}
},
methods: {
testClick () {
this.testMsg = "newValue";
console.log(this.$refs.test.innerText); //this.$refs.test 獲取指定DOM 輸出為:oldValue 還是之前定義的值
}
}
}
</script>
使用this.$nextTick()
https://blog.csdn.net/weixin_42333548/article/details/102606546