JS实现页面滑到底部加载下一页数据

4,886 阅读2分钟

事情的起因是这样的...

1.png

今天,同学在群里请教老师问题,见老师没有回复,热心肠的我就替老师回答了一下,结果

2.png

3.png

最后这个艰巨的任务就落在了我的头上。

开始

先搭建个h5页面,写几行html和css代码

<div id="main">
    <div id="content">
        <ul id="ul">

        </ul>
    </div>
</div>
body {
	background-color: #eee;
}
#main {
	margin: 0 auto;
	width: 600px;
}
#content {
	position: absolute;
	width: 600px;
}
#ul {
	margin: 0;
	padding: 0;
}
#ul li {
	list-style-type: none;
	background-color: #2AC2D1;
	margin: 0;
	margin-top: 30px;
	border-radius: 10px;
	text-align: center;
	height: 60px;
	color: #fff;
}

下面开始写js功能部分的代码

这位同学的需求大概就是页面滑到底部时,加载一页数据,也就是分页的功能。这个功能的要点就是判断页面什么时候到了底部,需要加载数据先写个模拟接口请求数据的方法

// 模拟请求接口返回数据的方法
function mockApi(pagenum, pagesize) {
	return new Promise(function(resolve, reject) {
		let data = [];
		for (let i = 0; i < pagesize; i++) {
			data.push(`第${pagenum}页的数据--${i + 1}`);
		}
		resolve(data);
	})
}

请求方法返回数据之后需要将数据渲染到页面中

// 渲染dom的方法
function render(){
	mockApi(pagenum, pagesize).then(function(res) {
	for (let item of res) {
		let dom = document.createElement("li");
		dom.innerHTML = item;
		ul.appendChild(dom);
	}
	})
}

然后设置一些初始数据,页面加载执行第一次渲染

var pagenum = 1; // 页数
var pagesize = 20; // 每页多少条
const ul = document.getElementById("ul");
window.onload = function() {
	render(); // 页面加载完成渲染一次
}

这一步结束,可以看到是下面这样,滑到底部还是没有反应的,因为还没写功能代码

4.png

最后,也是这个功能的要点,让页面滑到底部的时候可以加载一页数据。通过window.onscroll事件监听页面的滚动,在事件监听的方法中判断如果滚动条距离顶部的距离 + 页面可视窗口的高度 > 网页总高度的时候,此时页面就到了最底部。代码如下:

window.onscroll = function() {
	//获取网页的总高度
	var htmlHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
	//clientHeight是网页在浏览器中的可视高度
	var clientHeight = document.body.clientHeight || document.documentElement.clientHeight;
	//scrollTop是浏览器滚动条的top位置
	var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
	//判断到底部了,为了避免一些问题,设置距离底部50px时就执行代码
        console.log(scrollTop + clientHeight, htmlHeight);
	if (scrollTop + clientHeight > htmlHeight - 50) {
		pagenum++; // 页码+1
		render();
	}
}

预览效果如下:

动画.gif

优化一下

通过预览的效果可以看到onscroll事件监听,执行的次数多很频繁,这样会影响性能,所以改写一下事件监听,添加一个防抖函数

把事件监听函数提取出来:

function scrollFn(){
	//获取网页的总高度
	var htmlHeight = document.body.scrollHeight || document.documentElement.scrollHeight;
	//clientHeight是网页在浏览器中的可视高度
	var clientHeight = document.body.clientHeight || document.documentElement.clientHeight;
	//scrollTop是浏览器滚动条的top位置
	var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
	//判断到底部了
	console.log(scrollTop + clientHeight  ,  htmlHeight)
	if (scrollTop + clientHeight > htmlHeight - 50) {
		pagenum++; // 页码+1
		render();
	}
}

写一个防抖函数

function debounce(fn, delay){
	let timeout;
	return function() {
		clearTimeout(timeout);
		timeout = setTimeout(()=>{
			fn.apply(this, arguments);
		},delay)
	}
}

重新设置监听:

window.onscroll = debounce(scrollFn, 200);