首頁 > 軟體

vant-list上拉載入onload事件觸發多次問題及解決

2023-01-18 14:00:56

vant-list上拉載入onload事件觸發多次

場景

3個tab頁籤切換時,呼叫不同介面,在某一個tab只要翻頁到>=2的情況,當它再點選到另一個tab的時候,另外一個tab就會連續呼叫兩次查詢介面

(因為它不僅觸發了created還觸發了onload事件:且順序為:進入created呼叫查詢介面,在.then之前,非同步查詢還未返回的時候,又會去觸發onload事件,在current+=1之後再次進行查詢)

知識點運用:

一、基礎用法

List 元件通過 loading 和 finished 兩個變數控制載入狀態,當元件捲動到底部時,會觸發 load事件並將 loading 設定成 true。

此時可以發起非同步操作並更新資料,資料更新完畢後,將 loading 設定成 false 即可。

若資料已全部載入完畢,則直接將 finished 設定成 true 即可。

二、List 的執行機制是什麼?

List 會監聽瀏覽器的捲動事件並計算列表的位置,當列表底部與可視區域的距離小於offset時,List會觸發一次 load 事件。

三、為什麼 List 初始化後會立即觸發 load 事件?

List 初始化後會觸發一次 load事件,用於載入第一屏的資料,這個特性可以通過immediate-check屬性關閉。

四、為什麼會連續觸發 load 事件?

如果一次請求載入的資料條數較少,導致列表內容無法鋪滿當前螢幕,List 會繼續觸發 load事件,直到內容鋪滿螢幕或資料全部載入完成。

因此你需要調整每次獲取的資料條數,理想情況下每次請求獲取的資料條數應能夠填滿一屏高度。

五、loading 和 finished 分別是什麼含義?

List有以下三種狀態,理解這些狀態有助於你正確地使用List元件:

  • 非載入中,loading為false,此時會根據列表捲動位置判斷是否觸發load事件(列表內容不足一螢幕時,會直接觸發)
  • 載入中,loading為true,表示正在傳送非同步請求,此時不會觸發load事件
  • 載入完成,finished為true,此時不會觸發load事件 在每次請求完畢後,需要手動將loading設定為false,表示載入結束

這次遇到的問題,可以利用第五點,解決方法:

在進入created的傳送請求之前,將this.loading = true , ⇒⇒⇒ (利用:載入中,loading為true,表示正在傳送非同步請求,此時不會觸發load事件),讓系統知道此時正在非同步請求資料,讓它別觸發onload事件

程式碼:

<van-list
  v-model="loading" class="van-list-style" :immediate-check="false"
  :finished="finished" :finished-text="finishedText"
  :error.sync="error" error-text="請求失敗,點選重新載入"
  @load="onLoad">
  <div class="list" v-if="dataList.length > 0">
    <div class="list-box2" v-for="(item,index) in dataList" :key="index" @click="handleClick(item)">
      ………………………………………
    </div>
  </div>
  <div v-if="noData" style="margin-top:30%">
    <img src="@/common/imgs/no-data.png" alt="" style="width:100%">
  </div>
</van-list>

data() {
   return {
     dataList:[],
     current:1,
     size:10,
     loading: false, // 上拉載入 ?????? 
     finished: false, // 上拉載入完畢
     error: false, // 是否展示錯誤
     finishedText:"沒有更多了",
     noData:false, // 是否展示沒有資料的圖片
     // offset: 100 // 卷軸與底部距離小於 offset 時觸發load事件
   }
 },

 created() {
   // 呼叫列表查詢介面
   this.init(this.tab)
 },

methods:{
 init(val) {
   if(val === '1') {
     this.createList(1,10)
   } 
 },
   
//查詢介面
createList(current,size) {
  let param = { current:current, size:size }
  
  // 重點!!!!!!!!!在這裡將loading置為true
  ***this.loading = true;***

  createList(param).then(res=>{
    let that = this
    if(res.status == true) {
   	 //賦值
      const dataList = res.body.records
      const pages = res.body.pages
      // 如果返回資料為空
      if(dataList == null || dataList.length === 0) {
        that.finished = true
        that.finishedText = "沒發現任何東西,去其他地方逛逛吧~"
        that.noData = true
        return
      }
      // 載入狀態結束  可以寫在這裡也可以寫在finally裡面
      that.loading = false;
      
      // 根據當前頁進行資料處理
      if(that.current === 1) {
        that.dataList = dataList
      } else {
        that.dataList = that.dataList.concat(dataList)
      }

      // xxx!!!最後一頁不足10條的情況 ,這樣寫實際有問題,因為如果是最後一頁為10條的情況,就會第二次去呼叫介面
      //if(dataList.length < that.size) {
       // that.finished = true
       //that.finishedText = '沒有更多了';
      //}

      // 使用這種!! 證明已經是最後一頁了
      if(that.current = pages) {
        that.finished = true
        that.finishedText = '沒有更多了';
      }
    }
  })
  .catch(err=>{this.error = true; })
  .finally(()=>{this.loading = false })
},

// 上拉重新整理
 onLoad() {
   this.current+=1
   this.createList(this.current,this.size)
 },
}

總結

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com