異步更新隊列:
請記住:**vue是依靠數據驅動視圖更新的,該更新的過程是異步的。**即:當偵聽到你的數據發生變化時, Vue將開啓一個隊列(該隊列被Vue官方稱爲異步更新隊列)。視圖需要等隊列中所有數據變化完成之後,再統一進行更新。示例:
<div id="myApp">
<input type="button" value="點我呀" @click="changeStr">
<p ref="myP">{{str}}</p>
</div>
<script>
new Vue({
el:"#myApp",
data:{
str:"公衆號 張培躍,關注它的人很少!"
},
methods:{
changeStr(){
this.str = "歡迎關注公衆號 張培躍,收看更多精彩內容!";
// 輸出結果:公衆號 張培躍,關注它的人很少!
console.log(this.$refs.myP.innerText)
}
}
})
</script>
通過以上示例的輸出結果可以有力證明:Vue 實現的響應式並不是數據發生變化之後視圖立即變化。
獲取更新之後的DOM
Vue官方爲了避免開發者直接接觸視圖,鼓勵大家以"數據驅動"的方式進行思考。但,現在的我們想基於更新後的視圖來搞點事情,該如何下手?
我們可以使用$nextTick(callback)。這裏的回調函數(callback)將在數據更新完成,視圖更新完畢之後被調用。
更改上個示例中的changeStr方法如下:
changeStr(){
this.str = "歡迎關注公衆號 張培躍,收看更多精彩內容!";
this.$nextTick(()=>{
// 輸出結果:我愛你中國,我親愛的母親!
console.log(this.$refs.myP.innerText);
});
this.str = "我愛你中國,我親愛的母親!"
}
從輸出的結果可以看出:我們可以通過$nextTick() 獲取到更新之後的DOM。
因爲 $nextTick() 返回一個 Promise 對象,所以我們也可以使用async/await語法完成相同的事情:
changeStr:async function(){
this.str = "歡迎關注公衆號 張培躍,收看更多精彩內容!";
this.str = "我愛你中國,我親愛的母親!"
await this.$nextTick();
console.log(this.$refs.myP.innerText);
}
或者
changeStr(){
this.str = "歡迎關注公衆號 張培躍,收看更多精彩內容!";
this.$nextTick().then(()=>{
// 輸出結果:我愛你中國,我親愛的母親!
console.log(this.$refs.myP.innerText);
});
this.str = "我愛你中國,我親愛的母親!"
}
應用場景
1、如果要在created()鉤子函數中進行的DOM操作,由於created()鉤子函數中還未對DOM進行任何渲染,所以無法直接操作,需要通過$nextTick()來完成。
created(){
this.$nextTick(()=>{
this.$refs.myP.innerText = "我是一隻小小小小鳥,想要飛,卻怎麼樣也飛不高!";
});
}
注:在created()鉤子函數中進行的DOM操作,不使用$nextTick()會報錯:
// Error in created hook: "TypeError: Cannot set property 'innerText' of undefined"
created(){
this.$refs.myP.innerText = "我是一隻小小小小鳥,想要飛,卻怎麼樣也飛不高!";
}
2、更新數據後,想要使用js對新的視圖進行操作時。示例(略)
3、在使用某些第三方插件時 ,這些插件需要dom動態變化後重新應用該插件,這時候就需要使用$nextTick()來重新應用插件的方法。示例(略)