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 Mobile页面跳转后未加载外部JS原因分析及解决
Mar 18 Javascript
jquery 获取表单元素里面的值示例代码
Jul 28 Javascript
简单的两种Extjs formpanel加载数据的方式
Nov 09 Javascript
js+css实现的圆角边框TAB选项卡滑动门代码分享(2款)
Aug 26 Javascript
JavaScript数组和对象的复制
Mar 21 Javascript
Vue 进阶教程之v-model详解
May 06 Javascript
vue.js 初体验之Chrome 插件开发实录
May 13 Javascript
JS非空验证及邮箱验证的实例
Aug 11 Javascript
解决Jstree 选中父节点时被禁用的子节点也会选中的问题
Dec 27 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
Dec 03 Javascript
解决vue组件中click事件失效的问题
Nov 09 Javascript
Vue 中 a标签上href无法跳转的解决方式
Nov 12 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下防止单引号,双引号在接受页面转义的设置方法
2008/09/25 PHP
php网站来路获取代码(针对搜索引擎)
2010/06/08 PHP
PHP逐行输出(ob_flush与flush的组合)
2012/02/04 PHP
QQ互联一键登录审核不通过的解决方案
2014/09/10 PHP
PHP实现冒泡排序的简单实例
2016/05/26 PHP
PHP PDO和消息队列的个人理解与应用实例分析
2019/11/25 PHP
解析使用js判断只能输入数字、字母等验证的方法(总结)
2013/05/14 Javascript
jQuery中nextUntil()方法用法实例
2015/01/07 Javascript
Javascript中Array用法实例分析
2015/06/13 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
EasyUI布局 高度自适应
2016/06/04 Javascript
ionic由于使用了header和subheader导致被遮挡的问题的两种解决方法
2016/09/22 Javascript
微信小程序 WXML、WXSS 和JS介绍及详解
2016/10/08 Javascript
关于Iframe父页面与子页面之间的相互调用
2016/11/22 Javascript
基于javascript实现的快速排序
2016/12/02 Javascript
js鼠标移动时禁止选中文字
2017/02/19 Javascript
微信小程序左右滑动切换页面详解及实例代码
2017/02/28 Javascript
详解如何使用Vue2做服务端渲染
2017/03/29 Javascript
React Native之prop-types进行属性确认详解
2017/12/19 Javascript
详解js动态获取浏览器或页面等容器的宽高
2019/03/13 Javascript
Vue 数据绑定的原理分析
2020/11/16 Javascript
python调用cmd命令行制作刷博器
2014/01/13 Python
初步探究Python程序的执行原理
2015/04/11 Python
Python+Socket实现基于UDP协议的局域网广播功能示例
2017/08/31 Python
python实现闹钟定时播放音乐功能
2018/01/25 Python
Python之csv文件从MySQL数据库导入导出的方法
2018/06/21 Python
Python元组知识点总结
2019/02/18 Python
python防止随意修改类属性的实现方法
2019/08/21 Python
SELENIUM自动化模拟键盘快捷键操作实现解析
2019/10/28 Python
一款基于css3和jquery实现的动画显示弹出层按钮教程
2015/01/04 HTML / CSS
微信浏览器取消缓存的方法
2015/03/28 HTML / CSS
详解移动端HTML5页面端去掉input输入框的白色背景和边框(兼容Android和ios)
2016/12/15 HTML / CSS
雪花秀美国官方网站:韩国著名草本护肤化妆品品牌
2016/10/19 全球购物
捷克电器和DJ设备网上商店:Electronic-star
2017/07/18 全球购物
Cotton On香港网站:澳洲时装连锁品牌
2018/11/01 全球购物
启迪人心的励志语录:脾气永远不要大于本事
2020/01/02 职场文书