上拉無限加載方案

上拉加載可行性實(shí)現(xiàn)方案及性能比對(duì)

關(guān)于上拉加載方案的確定,有多種實(shí)現(xiàn)方式,最初考慮監(jiān)聽頁面的滾動(dòng)事件,對(duì)消息列表最后一條消息位置進(jìn)行計(jì)算,判斷當(dāng)其出現(xiàn)在視口中時(shí),請(qǐng)求接口加載新的消息數(shù)據(jù),視圖持續(xù)更新,每次需要選中消息列表的最后一條消息進(jìn)行計(jì)算,處理有些復(fù)雜。綜合考慮各種方案及實(shí)現(xiàn)簡(jiǎn)便性,下面兩種方案可以進(jìn)行討論

方案1

監(jiān)聽頁面滾動(dòng)事件,獲取頁面根元素到視口頂部的距離x,獲取元素在視口中的高度y,獲取元素的實(shí)際高度z:

  • 消息列表在滾動(dòng)過程中未加載到底部時(shí),始終有x+y<z
  • 當(dāng)消息列表加載到底部時(shí),有x+y===z

為了防止頻繁觸發(fā)滾動(dòng)事件的監(jiān)聽事件,對(duì)滾動(dòng)事件進(jìn)行防抖處理,監(jiān)聽事件頻繁觸發(fā)時(shí),每隔著200ms再執(zhí)行一次任務(wù)
[這里有一張圖片]

實(shí)現(xiàn)的代碼也很簡(jiǎn)潔

  window.addEventListener('scroll', throttle(scrollEventHandler, 100))
  function scrollEventHandler () {
    let scrollTop = document.documentElement.scrollTop //元素頂部到視口頂部的距離
    let clientHeight = document.documentElement.clientHeight //獲取元素在視口中的高度,包括內(nèi)邊距,不過包括水平滾動(dòng)條/邊框/外邊距
    let scrollHeight = document.documentElement.scrollHeight //獲取元素實(shí)際的高度,包括內(nèi)邊距,不過包括水平滾動(dòng)條/邊框/外邊距
    if (scrollHeight === scrollTop + clientHeight) {
      //調(diào)用請(qǐng)求數(shù)據(jù)接口
    }
  }
  function debounce(fn, delay) {
    let timer = delay
    return function () {
      let context = this
      let args = arguments
      clearTimeout(timer)
      timer = setTimeout(function() {
        fn.apply(context, args)
      }, delay)
    }
  }

方案2

  • 考慮到監(jiān)聽消息列表的最后一條消息并計(jì)算其是否出現(xiàn)在視口,需要在每次dom更新完畢后重新選擇最后一條消息進(jìn)行計(jì)算其是否出現(xiàn)在視口中,因此想到一種比較便捷的實(shí)現(xiàn)方法。
  • 封裝一個(gè)公用的底部bar組件,始終置于消息列表尾部,根據(jù) Intersection Observer 方法判斷其是否出現(xiàn)在視口中,當(dāng)其出現(xiàn)在視口中,表示當(dāng)前消息頁面已經(jīng)加載到頁面底部。

    [這里也有一張圖片]
  • 這個(gè)種實(shí)現(xiàn)方案不需要監(jiān)聽頁面的滾動(dòng)事件,在實(shí)現(xiàn)上也比較方便??紤]到api的兼容性,以及鎖屏業(yè)務(wù)的實(shí)際場(chǎng)景,不需要再引入額外的polyfill文件

封裝的公用底bar組件,可以傳入當(dāng)?shù)?code>bar出現(xiàn)在視口中后相應(yīng)的加載事件,在消息加載完畢后停止對(duì)底bar元素的觀察

<template>
  <div v-if="isShow" class="bottom-bar">
    <div v-if="status==`loading`" class="bottom-bar-loading">
      <i class="bottom-bar-loading-icon"/>
      <span class="bottom-bar-txt loading-txt">正在加載...</span>
    </div>
    <span v-if="status==`completed`" class="bottom-bar-txt">已顯示全部消息</span>
    <span v-if="status==`poor-network`" class="bottom-bar-txt">網(wǎng)絡(luò)信號(hào)差,請(qǐng)重試</span>
    <span v-if="status==`no-connection`" class="bottom-bar-txt">無網(wǎng)絡(luò)連接,請(qǐng)?jiān)O(shè)置網(wǎng)絡(luò)</span>
    <span v-if="status==`no-service`" class="bottom-bar-txt">服務(wù)器異常,請(qǐng)上劃重試</span>
  </div>
</template>
<script>
  export default {
    name: 'BottomBar',
    props: {
      isShow: {
        type: Boolean,
        default: true
      },
      status: {
        type: String,
        default: 'loading'
      },
      loadMethod: {
        type: Function,
        required: true
      },
      observerConfig: {
        type: Object,
        required: true,
        default: {
          threshold: 0.5
        }
      }
    },
    computed: {
      observer() {
        return new IntersectionObserver(([entry]) => {
          if(entry && this.isShow && entry.isIntersecting) {
            this.loadMethod()
          }
        }, this.observerConfig)
      }
    },
    mounted() {
      this.observer.observe(this.$el) 
    },
    methods: {
      unobserver: function() {
        this.observer.unobserve(this.$el)
      }
    }
  }
</script>

父組件:

<template>
    <BottomBar :status="status" :load-method="getLikes" ref="bar"/>
</template>
<script>
  import BottomBar from './BottomBar'
  export default {
    components: {
      BottomBar
    },
    data() {
      return {
        status: 'loading'
      }
    },
    created() {
      //模板渲染成html前調(diào)用,初始化某些屬性值,渲染成視圖
    },
    computed(){
    },
    mounted() {  
      //模板渲染成html后調(diào)用,初始化頁面完成后,對(duì)htmldom節(jié)點(diǎn)進(jìn)行一些操作
    },
    methods: {
    }
  }
</script>

無限滾動(dòng)時(shí),最好在頁面底部有一個(gè)頁尾欄(又稱sentinels)。一旦頁尾欄可見,就表示用戶到達(dá)了頁面底部,從而加載新的條目放在頁尾欄前面。這樣做的好處是,不需要再一次調(diào)用observe()方法,現(xiàn)有的IntersectionObserver可以保持使用。

IntersectionObserver API 使用教程

判斷元素是否在視窗之內(nèi)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 言 午 小水滴吃飽後,她睡在搖藍(lán)裏,睜著兩只大眼望著我。她的眼睛像一彎靜靜的湖水,...
    言午57閱讀 364評(píng)論 0 3
  • 我曾想七夕和你去做蛋糕 我曾想十一月拉你出去旅游 我曾想明年陪你去學(xué)習(xí)廚藝,后年……大后年……總在一起努力奮斗。 ...
    蘑菇團(tuán)團(tuán)閱讀 293評(píng)論 4 3
  • 構(gòu)思這篇文章已經(jīng)有些日子了,今日朋友請(qǐng)吃飯看電影來晚了一會(huì)兒,市中心恰恰碰到一對(duì)姐妹花在賣唱,旁邊一塊牌子大概寫著...
    風(fēng)流人物閱讀 813評(píng)論 0 1
  • 稍了解公司法的伙伴都知道,有限責(zé)任公司與股份有限公司是公司的兩個(gè)基本形態(tài)。那么,今天要探討的股份合作公司是哪來的?...
    lawyer無畏閱讀 346評(píng)論 0 1
  • 一個(gè)蘿卜一個(gè)坑是最基本的標(biāo)配,當(dāng)少了一個(gè)蘿卜,多了一個(gè)坑就悲劇了,現(xiàn)在的我們就是這個(gè)樣子,工作量沒走減少反而多了,...
    李蘇珊閱讀 191評(píng)論 0 0

友情鏈接更多精彩內(nèi)容