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

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

实现数据无限加载的过程大致如下:
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
如果本篇内容对大家有帮助,请点击页面右下角的关注。如果觉得不好,也欢迎拍砖。你们的评价就是博主的动力!下篇内容,敬请期待!
JS实现-页面数据无限加载的更多相关文章
- js实现移动端无限加载分页
原理:当滚动条到达底部时,执行下一页内容. 判断条件需要理解三个概念: 1.scrollHeight 真实内容的高度 2.clientHeight 视窗的高度,即在浏览器中所能看到的内容的 ...
- js刷新页面得重新加载和页面的刷新
1.reload 方法,该方法强迫浏览器刷新当前页面. 语法:location.reload([bForceGet]) 参数: bForceGet, 可选参数, 默认为 false,从客户端缓存里取当 ...
- Vue.js 开发实践:实现精巧的无限加载与分页功能
本篇文章是一篇Vue.js的教程,目标在于用一种常见的业务场景--分页/无限加载,帮助读者更好的理解Vue.js中的一些设计思想.与许多Todo List类的入门教程相比,更全面的展示使用Vue.js ...
- 支持无限加载的js图片画廊插件
natural-gallery-js是一款支持无限加载的js图片画廊插件.该js图片画廊支持图片的懒加载,可以对图片进行搜索,分类,还可以以轮播图的方式来展示和切换图片. 使用方法 在页面中引入下面的 ...
- Ajax--PHP+JQuery+Ajax解析json、XML数据、加载页面
一.JQuery+Ajax用get.post方式提交和请求数据 知识要点: $('#userName').blur(function () { var txt = $(this).val(); $.a ...
- 为不同分辨率单独做样式文件,在页面头部用js判断分辨率后动态加载定义好的样式文件
为不同分辨率单独做样式文件,在页面头部用js判断分辨率后动态加载定义好的样式文件.样式文件命名格式如:forms[_屏幕宽度].css,样式文件中只需重新定义文本框和下拉框的宽度即可. 在包含的头文件 ...
- 在页面所有元素加载完成之后执行某个js函数
在页面所有元素加载完成之后执行某个js函数 http://lgscofield.iteye.com/blog/1884352
- jquery.imgpreload.min.js插件实现页面图片预加载
页面分享地址: http://wenku.baidu.com/link?url=_-G8miwbgDmEj6miyFtjit1duJggBCJmFjR2jky_G1VftD9eS9kwGOlFWAOR ...
- JS判断访问设备(userAgent)加载不同页面 JS判断客户端操作系统类型(platform)
//平台.设备和操作系统 var system ={ win : false, mac : false, xll : false }; //检测平台 var p = navigator.platfor ...
随机推荐
- ABP理论学习之N层架构
返回总目录 自从写这个系列博客之后,发现很多园友还是希望有个直接运行的demo,其实在github上就有官方的demo,我直接把这demo的链接放到这里吧,另外,我分析,这些找不到demo的同学,很可 ...
- HTML5- Canvas入门(七)
这是本系列的最后一篇入门文章,主要是对剩余的未说明的canvas方法来逐个介绍. 首先,如果你是一名擅长矢量设计的设计师,对Illustrator或者Fireworks很熟悉的话,那你肯定知道它们有一 ...
- Google分布式构建软件之四:分发构建结果
注:本文英文原文在google开发者工具组的博客上[需要FQ],以下是我的翻译,欢迎转载,但请尊重作者版权,注名原文地址. 之前的文章,介绍了Google在分布式构建软件过程中,如何把构建过程分发到许 ...
- MapReduce剖析笔记之一:从WordCount理解MapReduce的几个阶段
WordCount是一个入门的MapReduce程序(从src\examples\org\apache\hadoop\examples粘贴过来的): package org.apache.hadoop ...
- Android 6.0 权限申请辅助 ----PermissionsHelper
Android 6.0 权限申请辅助 ----PermissionsHelper 项目地址:https://github.com/didikee/PermissionsHelper Android 的 ...
- php后台修改人员表信息
显示info人员表里所有内容 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...
- iOS --------Crash 分析(一)
iOS Crash 分析(文一)- 开始 1. 名词解释 1. UUID 一个字符串,在iOS上每个可执行文件或库文件都包含至少一个UUID.目的是为了唯一识别这个文件. 2. dwarfdump 苹 ...
- Nginx服务器之 Nginx的基本配置
本文使用 Linux centos系统 一.Nginx虚拟主机的配置 虚拟主机:通常情况下,为了使每个服务器可以供更多用户使用,可以将一个服务器分为很多虚拟的子服务器,每个子服务器都是互相独立的.这些 ...
- WPF入门教程系列二十二——DataGrid示例(二)
DataGrid示例的后台代码 1) 通过Entity Framework 6.1 从数据库(本地数据库(local)/Test中的S_City表中读取城市信息数据,从S_ Province表中读取 ...
- ES6学习记录
前言 由于要学习React Native ,所以得用到ES6,故为运用React Native做一个铺垫 学习记录 一.变量 1.let let 与 var 作用相同,用于定义变量,但是作用域不同.不 ...