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 相关文章推荐
Jquery常用技巧收集整理篇
Nov 14 Javascript
JavaScript中setAttribute用法介绍
Jul 20 Javascript
javascript获取元素偏移量的方法有哪些
Jun 24 Javascript
jQuery实现提示密码强度的代码
Jul 15 Javascript
每天一篇javascript学习小结(Date对象)
Nov 13 Javascript
深入分析javascript中console命令
Aug 14 Javascript
AngularJS入门教程引导程序
Aug 18 Javascript
基于vue-cli 打包时抽离项目相关配置文件详解
Mar 07 Javascript
jQuery ajax仿Google自动提示SearchSuggess功能示例
Mar 28 jQuery
如何通过javaScript去除字符串两端的空白字符
Feb 06 Javascript
纯js实现无缝滚动功能代码实例
Feb 21 Javascript
vue 使用饿了么UI仿写teambition的筛选功能
Mar 01 Vue.js
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 curl_setopt()函数实例代码与参数分析
2011/06/02 PHP
PHP使用数组实现队列
2012/02/05 PHP
php session劫持和防范的方法
2013/11/12 PHP
php发送post请求函数分享
2014/03/06 PHP
ThinkPHP之M方法实例详解
2014/06/20 PHP
PHP实现基于栈的后缀表达式求值功能
2017/11/10 PHP
Firebug 字幕文件JSON地址获取代码
2009/10/28 Javascript
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
2011/05/24 Javascript
用最通俗易懂的代码帮助新手理解javascript闭包 推荐
2012/03/01 Javascript
js获取下拉列表的值和元素个数示例
2014/05/07 Javascript
用js的document.write输出的广告无阻塞加载的方法
2014/06/05 Javascript
js和jquery中循环的退出和继续学习记录
2014/09/06 Javascript
Javascript中For In语句用法实例
2015/05/14 Javascript
springMVC + easyui + $.ajaxFileUpload实现文件上传注意事项
2017/04/23 Javascript
bootstrap模态框远程示例代码分享
2017/05/22 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
2017/11/07 Javascript
NodeJS 中Stream 的基本使用
2018/07/30 NodeJs
node.js遍历目录的方法示例
2018/08/01 Javascript
深入浅析Vue中mixin和extend的区别和使用场景
2019/08/01 Javascript
JS前端广告拦截实现原理解析
2020/02/17 Javascript
记一次vue跨域的解决
2020/10/21 Javascript
JavaScript实现商品评价五星好评
2020/11/30 Javascript
Python循环语句中else的用法总结
2016/09/11 Python
Python基于递归算法实现的走迷宫问题
2017/08/04 Python
Python文件打开方式实例详解【a、a+、r+、w+区别】
2019/03/30 Python
使用Python对Dicom文件进行读取与写入的实现
2020/04/20 Python
SportsDirect.com马来西亚:英国第一体育零售商
2018/11/21 全球购物
IdealFit官方网站:女性蛋白质、补充剂和运动服装
2019/03/24 全球购物
LINUX下线程,GDI类的解释
2016/12/14 面试题
客户服务经理岗位职责
2014/01/29 职场文书
企业安全生产责任书
2014/04/14 职场文书
保安公司服务承诺书
2014/05/28 职场文书
售房协议书范本2014
2014/10/23 职场文书
2016年教育局“我们的节日——端午节”主题活动总结
2016/04/01 职场文书
Java 垃圾回收超详细讲解记忆集和卡表
2022/04/08 Java/Android
python数字图像处理之图像自动阈值分割示例
2022/06/28 Python