問題描述:
項目里有一個輪播圖,輪播圖的圖片數據從服務器獲取,用v-for生成DOM在頁面中顯示,輪播圖插件會通過new Swiper給DOM添加CSS、事件等,實現輪播效果。
在這里存在操作順序問題:當服務器返回圖片數據后,需要更新數據。數據更新后,v-for根據數據先加載完畢,輪播圖插件swiper再通過new Swiper操作DOM,否則輪播效果不會起效。
v-for生成DOM:
<div class="center"><div class="swiper-container" ref="mySwiper"><div class="swiper-wrapper"><div class="swiper-slide" v-for="imagesData in imagesList" :key="imagesData.id"><img :src="imagesData.imgUrl"></div></div><div class="swiper-pagination"></div><div class="swiper-button-prev"></div><div class="swiper-button-next"></div></div></div>
異步請求數據:
this.$store.dispatch('Home/getBannerList');//store語句const mutations = {setBannerList(state, data){state.bannerList = data;}
};const actions = {async getBannerList(context){let bannerData = await requestBannerImage();bannerData = bannerData.data;context.commit('setBannerList',bannerData);}
};
Swiper操作DOM:
let mySwiper = new Swiper('.swiper-container', {//開啟循環模式loop: true,// 如果需要分頁器pagination: {el: '.swiper-pagination',},// 如果需要前進后退按鈕navigation: {nextEl: '.swiper-button-next',prevEl: '.swiper-button-prev',},});
把邏輯處理放在mounted鉤子中,存在的問題:由于請求是異步獲取,在mounted中雖然其他DOM已經加載,但是數據還未完全返回,因此v-for還未執行完畢,相當于v-for的加載也是異步的。new Swiper時,v-for的DOM還未生成,因此對DOM操作無法生效。
解決方案:
使用nextTick()
簡單介紹nextTick(回調函數):等待下一次 DOM 更新刷新的工具方法。
當頁面中DOM發生變化時,并不會馬上更新頁面,而是把修改推入隊列,再統一處理。
nextTick()執行后,可以讓推入隊列中的DOM修改生效。nextTick中的回調會在修改生效后執行。
用watch()監聽列表數據的改變,列表數據改變后,用nextTick推到DOM上,再用Swiper操作DOM。
watch:{List:{handler(newValue, oldValue){this.$nextTick(()=>{... = new Swiper()})}}
}