阅读 4203

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

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

分析

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

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

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

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

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

踩坑

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

<div class="list">
  <ul>
    <li>这是一条新闻</li>
    <li>这是一条新闻</li>
    <li>这是一条新闻</li>
    <li>这是一条新闻</li>
    ...
  <ul>
</div>复制代码

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

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

升级

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

<div class="list">
  <ul>
    <li>这是一条新闻</li>
    <li>这是一条新闻</li>
    <li>这是一条新闻</li>
    <li>这是一条新闻</li>
    ...
  <ul>
  <div class="loading" style="display:none;">加载中...</div>
</div>复制代码

$(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。焦虑只会让事情变得更糟,所以有一句话希望与和我一样的小白共勉:不要停下来,但要记住:慢下来,才最快。

笔者注

博客内文章若不另外注明,均为原创。转载请注明出处,谢谢。

博客内容主要是对新知识的归纳、总结。记录博客的目的也是为了方便自己日后的巩固复习。欢迎大家提出文章中理解错误的地方,不胜感激。若文章对你有帮助,将是我的荣幸。

文章分类
前端