亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

首頁 > web前端 > uni-app > 正文

聊聊uniapp的scroll-view下拉加載

青燈夜游
發(fā)布: 2022-07-14 21:07:08
轉(zhuǎn)載
4139人瀏覽過

聊聊uniapp的scroll-view下拉加載

最近在做一個(gè)微信小程序的直播模塊,模塊里的聊天室功能是用scroll-view + 一維數(shù)組的形式展示的,而且也沒有進(jìn)行任何的優(yōu)化,導(dǎo)致用戶的體驗(yàn)感比較差

首先模擬一下優(yōu)化前的聊天室情況

1.gif

肉眼可見的蛋疼~

但是優(yōu)化還是得優(yōu)化滴,不優(yōu)化是不可能滴,但是在開始之前,我覺得有必要把優(yōu)化步驟拆分為以下兩點(diǎn)?

1. 不再使用scroll-into-view設(shè)置錨點(diǎn)

由于舊版本使用的是scroll-view + 一維數(shù)組的形式實(shí)現(xiàn)的,這就導(dǎo)致在數(shù)據(jù)添加后頁面總會顯示加載后的最后一條信息,而不是加載前的最后一條信息,因此上一任開發(fā)者使用了scroll-into-view屬性作為數(shù)據(jù)加載后的回位錨點(diǎn),但是由于錨點(diǎn)指向的切換和數(shù)據(jù)加載并不是同步發(fā)生的,這就導(dǎo)致出現(xiàn)回彈的現(xiàn)象

2. 大量數(shù)據(jù)的處理

因?yàn)槭橇奶焓夜δ?,因此不可避免的需要加載大量的用戶對話、圖片等內(nèi)容,又因?yàn)閟croll-view本身并不適合加載大量的數(shù)據(jù)(太菜了想不出來其他辦法),故而需要在數(shù)據(jù)的加載和顯示部分下點(diǎn)功夫處理一下

3. 附加功能處理

聊天室原本還有返回底部等功能存在,因此在完成優(yōu)化后原本的功能也不能忽略

OK開工~

1、倒置scroll-view

為什么要倒置scroll-view呢?從上面的第一點(diǎn)我們可以看出,如果需要正序地插入數(shù)據(jù),那么就會不可避免地出現(xiàn)數(shù)據(jù)加載后無法顯示后面數(shù)據(jù)的情況,但是想要解決這種情況又需要使用scroll-into-view屬性,那么如果需要徹底地解決這個(gè)問題,就需要從問題的根源scroll-view下手

首先是修改前的代碼?

<view class="live-content">這是一個(gè)直播畫面</view>
  <scroll-view
    class="scroll"
    :scroll-y="true"
    :scroll-into-view="scrollIntoView"
    @scrolltoupper="upper"
  >
    <view
      :id="item.index"
      :style="{
        backgroundColor: item.color,
        height: '200rpx',
        lineHeight: '200rpx',
        textAlign: 'center',
      }"
      v-for="item in scrollData"
      :key="item.index"
    >
      {{ item.data }}
    </view>
  </scroll-view>
登錄后復(fù)制
const scrollIntoView = ref("index1");
const upper = () => {
  let lastNum = scrollData.value[0].data;
  let newArr = [];
  for (let index = 1; index <= 10; index++) {
    newArr.push({
      color: getRandomColor(),
      data: lastNum + index,
      index: `index${lastNum + index}`,
    });
  }
  scrollData.value.unshift(...newArr.reverse());
  // 這里可以使用nextTick來替換一下,結(jié)果也是一樣的,但是為了更明顯的回彈效果我使用了定時(shí)器
  setTimeout(() => {
    scrollIntoView.value = `index${lastNum}`;
    console.log("scrollIntoView  :>>", scrollIntoView.value);
  }, 100);
};
const getRandomColor = () => {
  return "#" + Math.random().toString(16).substr(2, 6);
};
登錄后復(fù)制

那么就先來試一下倒置scroll-view到底也沒有效果

首先我們需要給scroll-view套上一個(gè)transform:rotate(180deg)的屬性,然后再給內(nèi)部的子元素也套上同樣的屬性,別忘了給存放數(shù)據(jù)的數(shù)組也倒置一下,最重要的,把scroll-view上的scroll-into-view屬性去掉,就會得到這樣的效果?

2.gif

還有就是此時(shí)滾動條的位置是在左邊的,如果有需要可以使用CSS屬性去掉,或者自行模擬,下面是去去除滾動條的CSS樣式?

::-webkit-scrollbar {
  display:none;
  width:0;
  height:0;
  color:transparent;
}
登錄后復(fù)制

到這里還只是第一步,下一步是如何下拉加載數(shù)據(jù)。

此時(shí)我們的scroll-view是處于倒置的狀態(tài),也就是說頂部是底,底部才是頂(擱著繞口令呢),所以之前使用的scrolltoupper觸頂方法要替換成scrolltolower觸底方法才能實(shí)現(xiàn)“下拉加載”

3.gif

下面是目前的聊天室看起來好多了

4.gif

2、大量數(shù)據(jù)的處理

處理完回彈問題后,就需要考慮如何處理大量數(shù)據(jù)。由于uni-app官方也在文檔中提到scroll-view加載大批量數(shù)據(jù)的時(shí)候性能較差,但無奈手頭上也沒有別的辦法,只能死馬當(dāng)活馬醫(yī)了

我第一個(gè)想法就是非常經(jīng)典的虛擬列表,但是此前所看的很多關(guān)于虛擬列表的文章都是在web端實(shí)現(xiàn)的,似乎小程序領(lǐng)域里并不是一個(gè)被經(jīng)常采用的方法,但是所幸還是找到了如何在微信小程序?qū)崿F(xiàn)虛擬列表的資料,詳情可以查看這篇文章?微信小程序虛擬列表

OK說干就干,那么第一步就是要明確實(shí)現(xiàn)虛擬列表需要什么樣的數(shù)據(jù)結(jié)構(gòu),虛擬列表其實(shí)簡單地說就是當(dāng)某一個(gè)模塊的數(shù)據(jù)超出了可視范圍就將其隱藏,那么如何將數(shù)據(jù)分為多個(gè)模塊呢?答案就是二維數(shù)組

首先將當(dāng)前的頁碼存儲起來(默認(rèn)為0),當(dāng)觸發(fā)下拉加載動作時(shí)頁碼+1,然后以當(dāng)前頁碼作為下標(biāo)存入數(shù)組

const currentShowPage=ref(0)
const upper = () => {
  let len = scrollData.value[currentShowPage.value].length - 1;
  let lastNum = scrollData.value[currentShowPage.value][len].data;
  let newArr = [];
  currentShowPage.value += 1;
  for (let index = 1; index <= 10; index++) {
    newArr.push({
      color: getRandomColor(),
      data: lastNum + index,
      index: `index${lastNum + index}`,
    });
  }
  scrollData.value[currentShowPage.value] = newArr;
};
登錄后復(fù)制

當(dāng)然別忘了在頁面中也需要以二維數(shù)組的形式循環(huán)數(shù)據(jù)

<scroll-view style="transform:rotate(180deg)" :scroll-y="true" @scrolltolower="upper">
    <view v-for="(data, index) in scrollData" :key="index">
      <view
         style="transform:rotate(180deg)" 
        :style="{
          backgroundColor: item.color,
          height: '200rpx',
          lineHeight: '200rpx',
          textAlign: 'center',
        }"
        v-for="item in data"
        :key="item.index"
      >
        {{ item.data }}
      </view>
    </view>
  </scroll-view>
登錄后復(fù)制
數(shù)據(jù)結(jié)構(gòu)的問題解決了,那么接下來就是如何判斷數(shù)據(jù)模塊是否超出可視范圍。

首先我們需要知道每個(gè)數(shù)據(jù)模塊的高度,其實(shí)很簡單,只需要為每個(gè)模塊定義一個(gè)id,然后在數(shù)據(jù)展示之后根據(jù)id獲取到該模塊的節(jié)點(diǎn)信息然后按順序存儲到數(shù)組中即可

const pagesHeight = []
onReady(()=>{
    setPageHeight()
})

const upper = () => {
  ...
  nextTick(() => {
    // 每次獲取新數(shù)據(jù)都調(diào)用一下
    setPageHeight();
  });
};

const setPageHeight = () => {
  let query = uni.createSelectorQuery();
  query
    .select(`#item-${currentShowPage.value}`)
    .boundingClientRect(res => {
      pagesHeight[currentShowPage.value] = res && res.height;
    })
    .exec();
};
登錄后復(fù)制

OK,現(xiàn)在我們已經(jīng)知道每個(gè)模塊的高度了,然后就是監(jiān)聽模塊與可視窗口的交叉范圍。這里有兩種方法,一種是JS獲取可視窗口的高度與模塊scrollTop進(jìn)行差值計(jì)算,另一種是使用小程序的createIntersectionObserver方法讓程序自行監(jiān)聽交叉區(qū)域

這里我展示的是第二種方法,如果對第一種方法感興趣的朋友可以向上看第二章開頭我推薦的《微信小程序虛擬列表》文章

關(guān)于createIntersectionObserver方法的使用其實(shí)很簡單,我們只需要把可視窗口的id以及需要監(jiān)聽的模塊id傳入即可,詳情看官方文檔

onReady(() => {
  ...
  observer(currentShowPage.value);
});
const upper = () => {
  ...
  nextTick(() => {
    // 每次獲取新數(shù)據(jù)都調(diào)用一下
    observer();
  });
};

// 允許渲染的數(shù)組下標(biāo),需要設(shè)置默認(rèn)值
const visiblePagesList = ref([-1,0,1])
const observer = pageNum => {
  const observeView = wx
    .createIntersectionObserver()
    .relativeTo("#scroll", { top: 0, bottom: 0 });
  observeView.observe(`#item-${pageNum}`, res => {
    if (res.intersectionRatio > 0) visiblePagesList.value = [pageNum - 1, pageNum, pageNum + 1];
  });
};
登錄后復(fù)制

最后就是在頁面中判斷該模塊是否允許被渲染(也就是是否存儲在visiblePagesList數(shù)組中),這里就很簡單了,只需要寫一個(gè)方法在頁面中調(diào)用即可

<scroll-view id="scroll" class="scroll" :scroll-y="true" @scrolltolower="upper">
    <view v-for="(data, index) in scrollData" :key="index" :id="'item-' + index">
      <template v-if="includePage(index)">
        <view
          class="scroll-item"
          :style="{
            ...
          }"
          v-for="item in data"
          :key="item.index"
        >
          {{ item.data }}
        </view>
      </template>
      <view v-else :style="{ height: pagesHeight[index] }"></view>
    </view>
  </scroll-view>
登錄后復(fù)制
const includePage = index => {
  return visiblePagesList.value.indexOf(index) > -1;
};
登錄后復(fù)制

來看看效果如何

5.gif

額...似乎沒有太大區(qū)別,那我們看看頁面結(jié)構(gòu)到底也沒有將可視區(qū)域外的內(nèi)容切換為空白view

6.gif

成功!

3、功能調(diào)整

聊天室原本還有回底功能等,也不能忘了加上

這個(gè)部分就比較簡單了,只需要直接使用scroll-view的scroll-top屬性,然后通過在scroll回調(diào)中動態(tài)記載scroll-top的值即可

下面是部分代碼

<scroll-view
    id="scroll"
    class="scroll"
    :scroll-y="true"
    :scroll-top="currentTop"
    @scroll="handle_scroll"
    @scrolltolower="upper"
  >
  ...
  </scroll-view>
  <view v-show="showGoBottom" class="go-back-btn" @click="handle_goBottom">回底</view>
登錄后復(fù)制
let scrollTop;
const currentTop = ref(0);
const showGoBottom = ref(false);
const handle_scroll = throttle(event => {
  scrollTop = event[0].detail.scrollTop;
  if (scrollTop > 300) {
    showGoBottom.value = true;
  }
}, 100);
const handle_goBottom = () => {
  currentTop.value = scrollTop;
  nextTick(() => {
    currentTop.value = 0;
  });
  showGoBottom.value = false;
};
登錄后復(fù)制

大功告成~

最后附上demo倉庫

https://gitee.com/huang-qihao123/virtual-list-demo

推薦:《uniapp教程

以上就是聊聊uniapp的scroll-view下拉加載的詳細(xì)內(nèi)容,更多請關(guān)注php中文網(wǎng)其它相關(guān)文章!

最佳 Windows 性能的頂級免費(fèi)優(yōu)化軟件
最佳 Windows 性能的頂級免費(fèi)優(yōu)化軟件

每個(gè)人都需要一臺速度更快、更穩(wěn)定的 PC。隨著時(shí)間的推移,垃圾文件、舊注冊表數(shù)據(jù)和不必要的后臺進(jìn)程會占用資源并降低性能。幸運(yùn)的是,許多工具可以讓 Windows 保持平穩(wěn)運(yùn)行。

下載
來源:掘金社區(qū)網(wǎng)
本文內(nèi)容由網(wǎng)友自發(fā)貢獻(xiàn),版權(quán)歸原作者所有,本站不承擔(dān)相應(yīng)法律責(zé)任。如您發(fā)現(xiàn)有涉嫌抄襲侵權(quán)的內(nèi)容,請聯(lián)系admin@php.cn
最新問題
開源免費(fèi)商場系統(tǒng)廣告
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長!
關(guān)注服務(wù)號 技術(shù)交流群
PHP中文網(wǎng)訂閱號
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號