JavaScript实现瀑布流无穷滚动加载
本文介绍如何使用JavaScript实现瀑布流布局下的无穷滚动加载功能。通过监听onscroll事件,结合自定义函数判断页面可视区域与最后一个数据块的位置关系,当满足特定条件时动态从后台获取数据并追加到DOM中,从而实现平滑的无限加载体验。
滚动加载原理
实现滚动加载功能首先需要利用onscroll事件处理程序来监听用户的滚动行为。
所谓无穷滚动,即用户滑动滚动条时,系统能够持续不断地加载新的数据块,无需手动翻页。
本文采用瀑布流布局来实现数据的无限加载。瀑布流布局的特点是一系列等宽但高度不等的图片块排列。在用户向下滚动时,系统会自动加载新数据。核心难点在于准确判断何时触发加载操作。

理解瀑布流布局的特性至关重要:新添加的图片总是被放置在当前所有列中高度最低的那一列。因此,当最后一个蓝色边框的图片加载完成后,意味着当前页面已无更多数据。我们需要确定一个触发点,即在最后一个图片加载到什么程度时发起滚动事件请求。图中灰色区域代表页面总高度,蓝色边框代表浏览器可视窗口高度。当滚动条拖动时,灰色区域相对上移。我们的目标是当页面最后一个图片(蓝色部分)加载至一半时触发滚动事件,为此需要建立相应的参照标准。
代码实现细节
接下来编写具体代码实现逻辑。
//检测是否具备滚动条加载数据块的条件
function checkScrollSlide(){
var oparent = document.getElementById('main');
var oBoxs = getByClass(oparent,'box');
var scrollH = document.body.scrollTop || document.documentElement.scrollTop + document.body.clientHeight || document.documentElement.clientHeight;
var lastBoxH = oBoxs[oBoxs.length - 1].offsetTop + Math.floor(oBoxs[oBoxs.length - 1].offsetHeight/2);
return (lastBoxH < scrollH )? true : false;
}
其中getClass函数是根据类名查找元素集合的自定义函数,后续将提供完整源码。
待加载的数据块结构如下:每个图片元素被一个class为pic的div包裹,所有数据块整体包含在父元素main中。
<div id = "main">
<div class = "box">
<div class = "pic">
<img src = "images/0.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/1.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/2.jpg">
</div>
</div>
<div>
实际应用中,数据块应从后台接口获取,此处使用JSON格式进行模拟演示。
var DataIn = {"data":[{"src":'0.jpg'},{"src":'1.jpg'},{"src":'2.jpg'},{"src":'3.jpg'},{"src":'4.jpg'},{"src":'5.jpg'}]};
上述代码展示了模拟的后台数据格式。
前文提到的函数返回一个布尔值,当条件满足(返回true)时,触发滚动加载事件。
滚动事件处理
window.onscroll = function(){
var oparent = document.getElementById('main');
//当满足加载条件时,就要向页面中加载数据块
if(checkScrollSlide){
for(var i = 0; i< DataIn.data.length; i++){
var oBox = document.createElement('div');
oBox.className = 'box';
oparent.appendChild(oBox);
var opic = document.createElement('div');
opic.className = 'pic';
oBox.appendChild(opic);
var oImg = document.createElement('img');
oImg.src = './images/'+DataIn.data[i].src;
opic.appendChild(oImg);
}
waterFull('main','box');
}
}
}
以下是完整源码展示。
包含CSS样式和HTML结构部分。
HTML与CSS结构
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8" />
<script src = "./jswaterfll.js"></script>
<title>瀑布流布局</title>
<style type="text/css">
*{
padding: 0px;
margin: 0px;
}
#main{
position: relative;
}
.box{
/* display: inline-block;*/
padding: 15px 0px 0px 15px;
float: left;
}
.pic{
padding: 10px;
border-radius: 5px;
border:1px solid #ccc;
box-shadow: 0 0 5px #ccc;
}
.pic img{
width: 165px;
height: auto;
}
</style>
</head>
<body>
<div id = 'main'>
<div class = "box">
<div class = "pic">
<img src = "images/3.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/4.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/20.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/21.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/2.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/3.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/4.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/5.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/6.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/7.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/8.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/9.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/10.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/11.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/17.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/18.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/19.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/4.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/5.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/6.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/7.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/8.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/11.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/12.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/13.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/14.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/15.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/16.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/17.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/18.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/19.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/20.jpg">
</div>
</div>
<div class = "box">
<div class = "pic">
<img src = "images/21.jpg">
</div>
</div>
</div>
</body>
</html>
JavaScript核心逻辑代码。
window.onload = function(){
waterFull('main','box');
var DataIn = {"data":[{"src":'0.jpg'},{"src":'1.jpg'},{"src":'2.jpg'},{"src":'3.jpg'},{"src":'4.jpg'},{"src":'5.jpg'}]};
window.onscroll = function(){
var oparent = document.getElementById('main');
if(checkScrollSlide){
for(var i = 0; i< DataIn.data.length; i++){
var oBox = document.createElement('div');
oBox.className = 'box';
oparent.appendChild(oBox);
var opic = document.createElement('div');
opic.className = 'pic';
oBox.appendChild(opic);
var oImg = document.createElement('img');
oImg.src = './images/'+DataIn.data[i].src;
opic.appendChild(oImg);
}
waterFull('main','box');
}
}
}
function waterFull(parent,children){
var oParent = document.getElementById(parent);
//var oBoxs = parent.querySelectorAll(".box");
var oBoxs = getByClass(oParent,children);
//计算整个页面显示的列数
var oBoxW = oBoxs[0].offsetWidth;
var cols = Math.floor(document.documentElement.clientWidth/oBoxW);
//设置main的宽度,并且居中
oParent.style.cssText = 'width:'+oBoxW * cols +'px; margin: 0 auto';
//找出高度最小的图片,将下一个图片放在下面
//定义一个数组,存放每一列的高度,初始化存的是第一行的所有列的高度
var arrH = [];
for(var i = 0; i< oBoxs.length ; i++){
if(i < cols){
arrH.push(oBoxs[i].offsetHeight);
}
else{
var minH = Math.min.apply(null,arrH);
var minIndex = getMinhIndex(arrH,minH);
oBoxs[i].style.position = 'absolute';
oBoxs[i].style.top= minH + 'px';
//oBoxs[i].style.left = minIndex * oBoxW + 'px';
oBoxs[i].style.left = oBoxs[minIndex].offsetLeft+'px';
arrH[minIndex] += oBoxs[i].offsetHeight;
}
}
}
function getByClass(parent,className){
var boxArr = new Array();//用来获取所有class为box的元素
oElement = parent.getElementsByTagName('*');
for (var i = 0; i <oElement.length; i++) {
if(oElement[i].className == className){
boxArr.push(oElement[i]);
}
};
return boxArr;
}
//获取当前最小值得下标
function getMinhIndex(array,min){
for(var i in array){
if(array[i] == min)
return i;
}
}
//检测是否具备滚动条加载数据块的条件
function checkScrollSlide(){
var oparent = document.getElementById('main');
var oBoxs = getByClass(oparent,'box');
var scrollH = document.body.scrollTop || document.documentElement.scrollTop + document.body.clientHeight || document.documentElement.clientHeight;
var lastBoxH = oBoxs[oBoxs.length - 1].offsetTop + Math.floor(oBoxs[oBoxs.length - 1].offsetHeight/2);
return (lastBoxH < scrollH )? true : false;
}
以上即为本文的全部内容,希望对读者的学习有所帮助,也欢迎大家继续支持本站。
JavaScript异步发送HTTP请求时怎么优雅地处理错误
2026-11-05 17:10:44
5款主流JS在线运行工具对比:CodePen、JSFiddle与StackBlitz怎么选
2026-11-05 17:04:04
JavaScript入门书籍避坑:这些书不适合初学者
2026-11-05 16:31:15
JS使用Math.round实现保留两位小数的原理与代码
2026-11-05 15:35:55
JavaScript 原生 Date 对象怎么实现日期加减
2026-11-05 14:30:00
