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与flash交互通信基础教程
Aug 07 Javascript
Ajax异步提交表单数据的说明及方法实例
Jun 22 Javascript
解决jquery1.9不支持browser对象的问题
Nov 13 Javascript
Flexigrid在IE下不显示数据的有效处理方法
Sep 04 Javascript
node.js中的fs.writeFile方法使用说明
Dec 14 Javascript
JavaScript中反正弦函数Math.asin()的使用简介
Jun 14 Javascript
Node.js使用orm2进行update操作时关联字段无法修改的解决方法
Jun 13 Javascript
vue.js实现备忘录功能的方法
Jul 10 Javascript
js比较两个单独的数组或对象是否相等的实例代码
Apr 28 Javascript
简单了解vue中父子组件如何相互传递值(基础向)
Jul 12 Javascript
JS操作json对象key、value的常用方法分析
Oct 29 Javascript
在Vue中使用CSS3实现内容无缝滚动的示例代码
Nov 27 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
实现在同一方法中获取当前方法中新赋值的session值解决方法
2014/06/26 PHP
Yii框架的路由配置方法分析
2019/09/09 PHP
jQuery EasyUI API 中文文档 - ProgressBar 进度条
2011/09/29 Javascript
JQuery的自定义事件代码,触发,绑定简单实例
2013/08/01 Javascript
浅析JavaScript原型继承的陷阱
2013/12/03 Javascript
Vue.js每天必学之内部响应式原理探究
2016/09/07 Javascript
Asp.Net之JS生成分页条的方法
2016/11/23 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
2016/12/14 Javascript
解析ajaxFileUpload 异步上传文件简单使用
2016/12/30 Javascript
HTML5+jQuery实现搜索智能匹配功能
2017/03/24 jQuery
Vue原理剖析 实现双向绑定MVVM
2017/05/03 Javascript
基于angular实现模拟微信小程序swiper组件
2017/06/11 Javascript
小程序指纹验证的实现代码
2018/12/04 Javascript
webpack file-loader和url-loader的区别
2019/01/15 Javascript
Flutter部件内部状态管理小结之实现Vue的v-model功能
2019/06/11 Javascript
如何用JS模拟实现数组的map方法
2020/07/30 Javascript
JavaScript实现网页下拉菜单效果
2020/11/20 Javascript
NodeJS配置CORS实现过程详解
2020/12/02 NodeJs
[01:18:31]DOTA2-DPC中国联赛定级赛 LBZS vs Magma BO3第一场 1月10日
2021/03/11 DOTA
Python转换HTML到Text纯文本的方法
2015/01/15 Python
浅谈Matplotlib简介和pyplot的简单使用——文本标注和箭头
2018/01/09 Python
python读取文件名称生成list的方法
2018/04/27 Python
Python实现调用另一个路径下py文件中的函数方法总结
2018/06/07 Python
Python基于最小二乘法实现曲线拟合示例
2018/06/14 Python
django做form表单的数据验证过程详解
2019/07/26 Python
python实现倒计时小工具
2019/07/29 Python
Django实现从数据库中获取到的数据转换为dict
2020/03/27 Python
提高python代码运行效率的一些建议
2020/09/29 Python
HTML5-WebSocket实现聊天室示例
2016/12/15 HTML / CSS
SQL Server 2000数据库的文件有哪些,分别进行描述。
2015/11/09 面试题
公益活动策划方案
2014/01/09 职场文书
表演方阵解说词
2014/02/08 职场文书
文明班级建设方案
2014/05/15 职场文书
导游词之淮安明祖陵
2019/11/25 职场文书
python plt.plot bar 如何设置绘图尺寸大小
2021/06/01 Python
在Oracle表中进行关键词搜索的过程
2022/06/10 Oracle