vue異步獲取數(shù)據(jù)解析
最近在用vue重構(gòu)有贊商城,在異步獲取數(shù)據(jù)的時候有些困惑,所以總結(jié)分享給大家泞遗,也希望大家能夠一起進步效扫。
場景顯示: 我們現(xiàn)在需要做一個輪播組件倔监,我們需要接收父組件傳遞過來的圖片數(shù)組(lists),所以父組件需要請求后端接口菌仁,從而獲取數(shù)組列表浩习。
1. 數(shù)據(jù)變化
數(shù)據(jù)流程.png
數(shù)據(jù)的到來分幾步階段 list: null
- 通過接口異步請求數(shù)據(jù) loading狀態(tài)
- 獲取回來的數(shù)據(jù):
- 有數(shù)據(jù) 渲染 list&&list.length > 0
- 無數(shù)據(jù) 空狀態(tài)的提示 list&&list.length = 0
父組件初始化要獲取的lists數(shù)組
// 父組件
data(){
return {
lists : null
}
},
created() {
this.getBanner()
}
methods: {
getBanner() {
// 獲取數(shù)據(jù)
axios.get(url.banner).then((res) => {
this.lists = res.data.lists || [];
})
}
}
2. 子組件接收數(shù)據(jù)的過程
子組件接收父組件的數(shù)據(jù)
- 當(dāng)異步請求還沒有得到數(shù)據(jù)的時候济丘,得到
lists = null
- 當(dāng)異步請求得到數(shù)據(jù)后谱秽,通過props,才能夠得到真正的數(shù)據(jù) 。
這里就有一個問題了
- 父組件剛開始傳遞的數(shù)據(jù)是null給子組件摹迷,但是子組件期望得到的是一個數(shù)組
父組件傳遞null.png
解決方案: 當(dāng)list=null
的時候不渲染子組件疟赊,當(dāng)數(shù)據(jù)到來的時候再進行渲染子組件
// 數(shù)據(jù)到來的時候渲染子組件
<swiper :lists= bannerLists name="swiper-banner" v-if="bannerLists"></swiper>
// 數(shù)組沒有到來的時候loading
<div v-else>loading</div>
子組件的代碼:
props: {
lists: {
type: Array,
required: true
},
// lists: {},
name: {}
},
// swiper必須要依賴dom
mounted() {
this.init();
},
methods: {
init() {
new Swiper('.swiper-container',{
loop: true,
pagination: '.swiper-pagination',
autoplay: 2000
})
}
},
解決方案: 如果我們不通過v-if來判定子組件是否渲染,而是通過子組件的生命周期函數(shù)進行處理
props: {
//lists: {
//type: Array,
//required: true
//},
lists: {}, //不能限定type峡碉,接收剛開始的null,和之后的數(shù)組lists
name: {}
},
// swiper必須要依賴dom
methods: {
init() {
new Swiper('.swiper-container',{
loop: true,
pagination: '.swiper-pagination',
autoplay: 2000
})
}
},
watch: {
//監(jiān)聽lists的變化(從null => 數(shù)組)
lists(val,oldVal) {
this.nextTick(() => {
this.init() //當(dāng)數(shù)據(jù)到來的時候近哟, DOM 更新循環(huán)結(jié)束之后,立即執(zhí)行函數(shù)
})
}
}
解析: 這里為什么需要使用this.nextTick()
呢异赫?當(dāng)我們監(jiān)聽到lists發(fā)生變化的時候椅挣,數(shù)據(jù)雖然到來了,但是通過數(shù)據(jù)渲染到的對應(yīng)dom還沒有執(zhí)行塔拳,我們還不能獲取到對應(yīng)的dom鼠证,只能通過異步的方式處理(this.nextTick())
<template>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swp-page swiper-slide" v-for="list in lists">
<a class="js-no-follow" :href="list.clickUrl">

</a>
</div>
</div>
<div class="swiper-pagination"></div>
</div>
</template>
<script>
watch: {
lists(val,oldval){
console.log(document.querySelector('.swiper-container')) //可以獲取
console.log(`val++++${val}`);
console.log(document.querySelectorAll('.swiper-slide')) //不能獲取
this.$nextTick(() => {
if(val){
this.init();
}
console.log(document.querySelectorAll('.swiper-slide')) //可以獲取
})
}
}
</script>
要確定dom已經(jīng)渲染完畢,如果有初始數(shù)據(jù)靠抑,在mounted這個階段dom已經(jīng)渲染完畢量九。如果通過watch來監(jiān)聽數(shù)據(jù)的變化,數(shù)據(jù)變化后不是馬上渲染dom的,是等到下次事件隊列來處理的荠列,就需要用到nextTick类浪。
? 關(guān)于nextTick可以查看