简单记录上拉加载更多实现思路

原文链接

下拉刷新、上拉加载更多是移动端常见的交互效果,也有很多封装好的库供我们方便的调用。但是如果只是一个简单的临时页面,也许不用第三方库手写实现会是一个不错的选择。今天就来简单说说上拉加载更多的实现思路。

分析

把上拉加载更多这个过程拆解一下,可以分成这几个步骤:

  • 页面向下滚动...
  • 页面滚动到了底部
  • 此时,显示加载动画,并发送ajax请求
  • 在请求成功后,隐藏加载动画,填充数据

通过以上步骤,不难发现,这个过程最关键的一步就是判断是否滚动到底部了。要完成这个判断,需要先来了解一下三个长度单位的概念:

  • 文档高度:即整个网页内容的实际高度,这部分高度可能会有一部分是现在看不到,需要滚动一下滚动条才能看到的。
  • 视口高度:即你能在浏览器里看到的网页内容的区域的高度。调整浏览器窗口的高度这个值会随之变化。
  • 滚动条位置:准确来讲是窗口垂直滚动条距离顶端的距离。

如果滚动条滚动到了底部,它们之间满足这个公式:文档高度 - 视口高度 - 滚动条位置 == 0。为了方便DOM操作,省去繁琐的兼容处理。使用jQuery来表示:$(document).height() - $(window).height() - $(window).scrollTop() == 0

踩坑

搞清楚了关键的一步,似乎挺简单的,是时候用代码来实现上面的过程了:

  • 这是一条新闻
  • 这是一条新闻
  • 这是一条新闻
  • 这是一条新闻
  • ...
$(function(){
  var $list = $('.list');
  var htmlNodes = '';
  $(window).scroll(function(){
    // 为了体验更好,在滚动到顶部之前50px(这个值也可以是其他的,按需求来)的位置时执行关键操作
    if($(document).height() - $(window).height() - $(window).scrollTop() > 50){
      $list.append('
加载中...
') // 用定时器模拟ajax请求的异步操作 setTimeout(function(){ $('.loading').remove(); for(var i = 0; i < 10; i++){ htmlNodes += '
  • 这是一条新闻
  • '; } $list.html(htmlNodes); }, 1000); } }); });

    以上的demo用定时器模拟了ajax请求获取数据的操作,似乎没有什么问题,但是实际运行的时候,滚动到底部的时候,会看到在列表底部追加了多个加载中...节点。这说明if语句块执行了多次,这是因为$(winow).scroll()是以一个很高频率被触发的,比如说滚动滚轮的时候,一秒钟内可能执行了多次$(winow).scroll()。要解决这个问题,需要添加一个全局标识isEnd = false;在滚动到底部时isEnd = true;,然后在请求完成,新的数据渲染完毕时再isEnd = false;,并且在上面的if语句块之前进行这个标识的判断if isEnd return;

    升级

    踩了以遍坑之后,把上面的代码升级一下(另外把加载中的添加移除节点改为显示和隐藏)。

    • 这是一条新闻
    • 这是一条新闻
    • 这是一条新闻
    • 这是一条新闻
    • ...
    $(function(){
      var $list = $('.list');
      var $loading = $('.loading');
      var htmlNodes = '';
      var isEnd = false;
      var page = 0;
      $(window).scroll(function(){
        if(isEnd) {
          return;
        }
        if($(document).height() - $(window).height() - $(window).scrollTop() > 50){
          $.ajax({
            type: 'POST',
            url: 'somePostUrl',
            data: {
              page: page++
            },
            dataType: 'json',
            success: function(res){
              // render the list
            },
            beforeSend: function(){
              $loading.show();
            },
            complete: function(){
              $loading.hide();
            }
          });
        }
      });
    });
    

    结语

    上面的内容很基础,但也是自己学习的一个总结吧,有错误的地方还望指正。最近比较浮,面对更新迭代如此迅速的前端,感觉有点无所适从。听说vue3都快要到来了,而我却还没有用vue写过一个完整的项目。ES都到ES7,ES8了,而我还在用ES5。焦虑只会让事情变得更糟,所以有一句话希望与和我一样的小白共勉:不要停下来,但要记住:慢下来,才最快。

    你可能感兴趣的:(简单记录上拉加载更多实现思路)