上拉无限加载方案

上拉加载可行性实现方案及性能比对

关于上拉加载方案的确定,有多种实现方式,最初考虑监听页面的滚动事件,对消息列表最后一条消息位置进行计算,判断当其出现在视口中时,请求接口加载新的消息数据,视图持续更新,每次需要选中消息列表的最后一条消息进行计算,处理有些复杂。综合考虑各种方案及实现简便性,下面两种方案可以进行讨论

方案1

监听页面滚动事件,获取页面根元素到视口顶部的距离x,获取元素在视口中的高度y,获取元素的实际高度z:

  • 消息列表在滚动过程中未加载到底部时,始终有x+y<z
  • 当消息列表加载到底部时,有x+y===z

为了防止频繁触发滚动事件的监听事件,对滚动事件进行防抖处理,监听事件频繁触发时,每隔着200ms再执行一次任务
[这里有一张图片]

实现的代码也很简洁

  window.addEventListener('scroll', throttle(scrollEventHandler, 100))
  function scrollEventHandler () {
    let scrollTop = document.documentElement.scrollTop //元素顶部到视口顶部的距离
    let clientHeight = document.documentElement.clientHeight //获取元素在视口中的高度,包括内边距,不过包括水平滚动条/边框/外边距
    let scrollHeight = document.documentElement.scrollHeight //获取元素实际的高度,包括内边距,不过包括水平滚动条/边框/外边距
    if (scrollHeight === scrollTop + clientHeight) {
      //调用请求数据接口
    }
  }
  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

  • 考虑到监听消息列表的最后一条消息并计算其是否出现在视口,需要在每次dom更新完毕后重新选择最后一条消息进行计算其是否出现在视口中,因此想到一种比较便捷的实现方法。
  • 封装一个公用的底部bar组件,始终置于消息列表尾部,根据 Intersection Observer 方法判断其是否出现在视口中,当其出现在视口中,表示当前消息页面已经加载到页面底部。

    [这里也有一张图片]
  • 这个种实现方案不需要监听页面的滚动事件,在实现上也比较方便。考虑到api的兼容性,以及锁屏业务的实际场景,不需要再引入额外的polyfill文件

封装的公用底bar组件,可以传入当底bar出现在视口中后相应的加载事件,在消息加载完毕后停止对底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">网络信号差,请重试</span>
    <span v-if="status==`no-connection`" class="bottom-bar-txt">无网络连接,请设置网络</span>
    <span v-if="status==`no-service`" class="bottom-bar-txt">服务器异常,请上划重试</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前调用,初始化某些属性值,渲染成视图
    },
    computed(){
    },
    mounted() {  
      //模板渲染成html后调用,初始化页面完成后,对htmldom节点进行一些操作
    },
    methods: {
    }
  }
</script>

无限滚动时,最好在页面底部有一个页尾栏(又称sentinels)。一旦页尾栏可见,就表示用户到达了页面底部,从而加载新的条目放在页尾栏前面。这样做的好处是,不需要再一次调用observe()方法,现有的IntersectionObserver可以保持使用。

IntersectionObserver API 使用教程

判断元素是否在视窗之内

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 言 午 小水滴吃飽後,她睡在搖藍裏,睜著兩只大眼望著我。她的眼睛像一彎靜靜的湖水,...
    言午57阅读 284评论 0 3
  • 我曾想七夕和你去做蛋糕 我曾想十一月拉你出去旅游 我曾想明年陪你去学习厨艺,后年……大后年……总在一起努力奋斗。 ...
    蘑菇团团阅读 237评论 4 3
  • 构思这篇文章已经有些日子了,今日朋友请吃饭看电影来晚了一会儿,市中心恰恰碰到一对姐妹花在卖唱,旁边一块牌子大概写着...
    风流人物阅读 732评论 0 1
  • 稍了解公司法的伙伴都知道,有限责任公司与股份有限公司是公司的两个基本形态。那么,今天要探讨的股份合作公司是哪来的?...
    环环lawyer阅读 290评论 0 1
  • 一个萝卜一个坑是最基本的标配,当少了一个萝卜,多了一个坑就悲剧了,现在的我们就是这个样子,工作量没走减少反而多了,...
    李苏珊阅读 119评论 0 0