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调试说明
Jun 07 Javascript
jQuery Study Notes学习笔记 (二)
Aug 04 Javascript
Javascript 中的 call 和 apply使用介绍
Feb 22 Javascript
向当前style sheet中插入一个新的style实现方法
Apr 01 Javascript
javascript 构造函数方式定义对象
Jan 02 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
Oct 25 Javascript
限制只能输入数字的实现代码
May 16 Javascript
jQuery事件与动画基础详解
Feb 23 Javascript
基于node.js express mvc轻量级框架实践
Sep 14 Javascript
webpack项目轻松混用css module的方法
Jun 12 Javascript
详解一个基于套接字实现长连接的express
Mar 28 Javascript
Ajax实现异步加载数据
Nov 17 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
php文件上传类完整实例
2016/05/14 PHP
PHP编写文件多服务器同步程序
2016/07/02 PHP
php实现不通过扩展名准确判断文件类型的方法【finfo_file方法与二进制流】
2017/04/18 PHP
JavaScript语句可以不以;结尾的烦恼
2007/03/08 Javascript
JavaScript中的排序算法代码
2011/02/22 Javascript
目前流行的JavaScript库的介绍及对比
2013/09/29 Javascript
JavaScript的setAttribute兼容性问题解决方法
2013/11/11 Javascript
js实现弹窗插件功能实例代码分享
2013/12/12 Javascript
jquery移除、绑定、触发元素事件使用示例详解
2014/04/10 Javascript
js实现的点击数量加一可操作数据库
2014/05/09 Javascript
Javascript中Array用法实例分析
2015/06/13 Javascript
JS获取复选框的值,并传递到后台的实现方法
2016/05/30 Javascript
Ionic实现页面下拉刷新(ion-refresher)功能代码
2016/06/03 Javascript
正则表达式(语法篇推荐)
2016/06/24 Javascript
360提示[高危]使用存在漏洞的JQuery版本的解决方法
2017/10/27 jQuery
Vue 页面跳转不用router-link的实现代码
2018/04/12 Javascript
详解webpack 最简打包结果分析
2019/02/20 Javascript
详解js加减乘除精确计算
2019/03/19 Javascript
vue+elementUI实现表单和图片上传及验证功能示例
2019/05/14 Javascript
layui自定义插件citySelect实现省市区三级联动选择
2019/07/26 Javascript
[00:44]TI7不朽珍藏III——军团指挥官不朽展示
2017/07/15 DOTA
Python的Django框架中的URL配置与松耦合
2015/07/15 Python
python OpenCV学习笔记直方图反向投影的实现
2018/02/07 Python
python使用matplotlib画饼状图
2018/09/25 Python
在numpy矩阵中令小于0的元素改为0的实例
2019/01/26 Python
python读写配置文件操作示例
2019/07/03 Python
python GUI库图形界面开发之pyinstaller打包python程序为exe安装文件
2020/02/26 Python
2014年创卫实施方案
2014/02/18 职场文书
社区矫正工作方案
2014/06/04 职场文书
2014大学生学生会工作总结
2014/12/19 职场文书
企业党建工作总结2015
2015/05/26 职场文书
2016年教师学习教师法心得体会
2016/01/20 职场文书
Python超简单容易上手的画图工具库推荐
2021/05/10 Python
python b站视频下载的五种版本
2021/05/27 Python
SpringBoot整合MongoDB的实现步骤
2021/06/23 MongoDB
nginx服务器的下载安装与使用详解
2021/08/02 Servers