JS实现页面数据无限加载


Posted in Javascript onSeptember 13, 2016

在手机端浏览网页时,经常使用一个功能,当我们浏览京东或者淘宝时,页面滑动到底部,我们看到数据自动加载到列表。之前并不知道这些功能是怎么实现的,于是自己在PC浏览器上模拟实现这样的功能。先看看浏览效果:

当滚动条滚动到页面底部时,提示“正在加载…”。

JS实现页面数据无限加载 

当页面已经加载了所有数据后,滚动到页面底部会提示“数据已加载到底了”:

JS实现页面数据无限加载

实现数据无限加载的过程大致如下:

1.滚动条滚动到页面底部。

2.触发ajax加载,把请求返回的数据加载到列表后面。

如何判断滚动条是否滚动到页面底部?我们可以设置一个规则:当滚动条的滚动高度和整个文档高度相差不到20像素,则认为滚动条滚动到页面底部了:

文档高度 - 视口高度 - 滚动条滚动高度 < 20

要通过代码实现这样的判断,我们必须要了解上面的这些高度通过哪些代码获取?可以参考我之前写的一篇“HTML元素坐标定位,这些知识点得掌握”。

上面的判断,我封装了一个方法: 

//检测滚动条是否滚动到页面底部
 function isScrollToPageBottom(){
 //文档高度
 var documentHeight = document.documentElement.offsetHeight;
 var viewPortHeight = getViewportSize().h;
 var scrollHeight = window.pageYOffset ||
  document.documentElement.scrollTop ||
  document.body.scrollTop || 0;

 return documentHeight - viewPortHeight - scrollHeight < 20;
 }

判断有了,我们就可以开启一个定时器,900毫秒监测一次,如果isScrollToPageBottom()返回true则调用ajax请求数据,如果返回false则通过900毫秒之后再监测。

下面是核心代码实现: 

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>无限分页</title>
 <link rel="stylesheet" href="assets/css/index.css"/>
</head>
<body>
<div class="l-page">
 <ul id="list" class="list">
 </ul>
</div>
<script src="//cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
<script src="js/jquery.mockjax.js"></script>
<script type="text/javascript" src="js/dataMock.js"></script>
<script type="text/javascript">
 //作为一个对象的w和h属性返回视口的尺寸
 function getViewportSize(w){
 //使用指定的窗口, 如果不带参数则使用当前窗口
 w = w || window;

 //除了IE8及更早的版本以外,其他浏览器都能用
 if(w.innerWidth != null)
  return {w: w.innerWidth, h: w.innerHeight};

 //对标准模式下的IE(或任意浏览器)
 var d = w.document;
 if(document.compatMode == "CSS1Compat")
  return {w: d.documentElement.clientWidth, h: d.documentElement.clientHeight};

 //对怪异模式下的浏览器
 return {w: d.body.clientWidth, h: d.body.clientHeight};
 }

 //检测滚动条是否滚动到页面底部
 function isScrollToPageBottom(){
 //文档高度
 var documentHeight = document.documentElement.offsetHeight;
 var viewPortHeight = getViewportSize().h;
 var scrollHeight = window.pageYOffset ||
  document.documentElement.scrollTop ||
  document.body.scrollTop || 0;

 return documentHeight - viewPortHeight - scrollHeight < 20;
 }

 //商品模板
 function getGoodsTemplate(goods){
 return "<li>" +
  "<div class='pic-wrap leftFloat'>" +
  "<img src='" + goods.pic + "'>" +
  "</div>" +
  "<div class='info-wrap leftFloat'>" +
  "<div class='info-name'><span>" + goods.name + "</span></div>" +
  "<div class='info-address'><span>" + goods.address +"</span></div>" +
  "<div class='info-bottom'>" +
  "<div class='info-price leftFloat'><span>¥" + goods.price + "</span></div>" +
  "<div class='info-star leftFloat'><span>" + goods.star + "人推荐</span></div>" +
  "<div class='info-more leftFloat'><span>更多信息</span></div>" +
  "</div>" +
  "</div>" +
  "</li>";
 }

 //初始化的时候默给list加载100条数据
 $.ajax("http://localhost:8800/loadData?sessionId=" + (+ new Date)).done(function(result){
 if(result.status){
  var html = "";
  result.data.forEach(function(goods){
  html += getGoodsTemplate(goods);
  });
  $("#list").append(html);
 }
 });


 //加载数据
 function loadDataDynamic(){
 //先显示正在加载中
 if( $("#loadingLi").length === 0)
  $("#list").append("<li id='loadingLi' class='loading'>正在加载...</li>");
 else{
  $("#loadingLi").text("正在加载...").removeClass("space");
 }
 var loadingLi = document.getElementById("loadingLi");
 loadingLi.scrollIntoView();
 //加载数据,数据加载完成后需要移除加载提示
 var hasData = false, msg = "";
 $.ajax("http://localhost:8800/loadData?sessionId=" + (+ new Date)).done(function(result){
  if(result.status){
  if(result.data.length > 0){
   hasData = true;
   var html = "";
   result.data.forEach(function(goods){
   html += getGoodsTemplate(goods);
   });
   $("#list").append(html);
  }else{
   msg = "数据已加载到底了"
  }
  }
  $("#list").append(loadingLi);
 }).fail(function(){
  msg = "数据加载失败!";
  }).always(function(){
  !hasData && setTimeout(function(){
  $(document.body).scrollTop(document.body.scrollTop -40);
  }, 500);
  msg && $("#loadingLi").text(msg);
  //重新监听滚动
  setTimeout(watchScroll, 900);
  });
 }

 //如果滚动条滚动到页面底部,需要加载新的数据,并且显示加载提示
 function watchScroll(){
 if(!isScrollToPageBottom()){
  setTimeout( arguments.callee, 900);
  return;  }
 loadDataDynamic();
 }

 //开始检测滚动条
 watchScroll();
</script>
</body>
</html>

demo中ajax请求我是通过jquery-mockjax模拟的数据。代码如下: 

/**
 * 模拟接口.
 */
var i = 0, len = 200, addresses = ["四川", "北京", "上海", "广州", "深圳", "甘肃", "云南", "浙江", "青海", "贵州"];


function getData(){
 var size = Math.min(i + 50, len), arr = [];
 for(; i < size; i++){
 arr.push({
  name: "苹果" + (i % 10 + 1),
  pic: "assets/images/iphone" + (i % 10 + 1) + ".jpg",
  price: parseInt(Math.random() * 10000),
  star: parseInt(Math.random() * 1000),
  address: addresses[i % 10]
 })
 }

 return arr;
}

$.mockjax({
 url: 'http://localhost:8800/loadData*',
 responseTime: 1000,
 response: function(settings){
 this.responseText = {
  status: true,
  data: getData()
 }
 }
});

整个完整的demo我已上传到github上:
 https://github.com/heavis/pageLoader

在线演示:
 https://heavis.github.io/pageLoader/index.html

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript中的getUTCDay()方法使用详解
Jun 10 Javascript
jQuery鼠标事件汇总
Aug 30 Javascript
简洁实用的BootStrap jQuery手风琴插件
Aug 31 Javascript
JavaScript中setTimeout的那些事儿
Nov 14 Javascript
Vue2.0使用过程常见的一些问题总结学习
Apr 10 Javascript
Vuex之理解state的用法实例
Apr 19 Javascript
weebox弹出窗口不居中显示的解决方法
Nov 27 Javascript
使用watch监听路由变化和watch监听对象的实例
Feb 24 Javascript
Vue引入sass并配置全局变量的方法
Jun 27 Javascript
jquery向后台提交数组的代码分析
Feb 20 jQuery
Vue切换组件实现返回后不重置数据,保留历史设置操作
Jul 21 Javascript
TypeScript实用技巧 Nominal Typing名义类型详解
Sep 23 Javascript
jQuery实现可展开折叠的导航效果示例
Sep 12 #Javascript
jQuery简单实现列表隐藏和显示效果示例
Sep 12 #Javascript
jQuery实现弹出带遮罩层的居中浮动窗口效果
Sep 12 #Javascript
jQuery实现的无限级下拉菜单功能示例
Sep 12 #Javascript
jQuery实现的图片轮播效果完整示例
Sep 12 #Javascript
Vue组件BootPage实现简单的分页功能
Sep 12 #Javascript
jQuery实现的多张图无缝滚动效果【测试可用】
Sep 12 #Javascript
You might like
为什么夜间收到的中波电台比白天多
2021/03/01 无线电
php中定义网站根目录的常用方法
2010/08/08 PHP
php实现用手机关闭计算机(电脑)的方法
2015/04/22 PHP
如何在PHP环境中使用ProtoBuf数据格式
2020/06/19 PHP
怎么让脚本或里面的函数在所有图片都载入完毕的时候执行
2006/10/17 Javascript
jQueryUI的Dialog的简单封装
2010/06/07 Javascript
js二维数组排序的简单示例代码
2014/01/24 Javascript
JS获取几种URL地址的方法小结
2014/02/26 Javascript
jquery使用jxl插件导出excel示例
2014/04/14 Javascript
json字符串之间的相互转换示例代码
2014/08/21 Javascript
字段太多jquey快速清空表单内容方法
2014/08/21 Javascript
基于jQuery实现在线选座之高铁版
2015/08/24 Javascript
js实现仿微博滚动显示信息的效果
2015/12/21 Javascript
JS生成某个范围的随机数【四种情况详解】
2016/04/20 Javascript
JavaScript操作 url 中 search 部分方法函数
2016/06/15 Javascript
vue-router路由懒加载和权限控制详解
2017/12/13 Javascript
vue mvvm数据响应实现
2020/11/11 Javascript
Nest.js环境变量配置与序列化详解
2021/02/21 Javascript
[56:35]DOTA2上海特级锦标赛主赛事日 - 5 总决赛Liquid VS Secret第一局
2016/03/06 DOTA
Django框架实现的简单分页功能示例
2018/12/04 Python
python按比例随机切分数据的实现
2019/07/11 Python
python支付宝支付示例详解
2019/08/22 Python
利用python实现周期财务统计可视化
2019/08/25 Python
Python Selenium 设置元素等待的三种方式
2020/03/18 Python
python 发送邮件的四种方法汇总
2020/12/02 Python
详解HTML5中div和section以及article的区别
2015/07/14 HTML / CSS
AmazeUI 评论列表的实现示例
2020/08/13 HTML / CSS
金山毒霸系列的笔试题
2013/04/13 面试题
考博自荐信
2013/10/25 职场文书
开业庆典邀请函
2014/01/08 职场文书
小学生感恩老师演讲稿
2014/08/28 职场文书
校园主题婚礼活动策划方案
2014/09/15 职场文书
中学生勤俭节约倡议书
2015/04/29 职场文书
病假条格式范文
2015/08/17 职场文书
【海涛教你打DOTA】剑圣第一人称视角解说
2022/04/01 DOTA
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
2022/04/24 Java/Android