這是手機端常見的一個功能,可能很多人都是用框架或者插件實現。
這裏,我試着用原生js實現。
這樣能更明白原理與底層實現
首先,佈局,模擬初始數據
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Document</title>
<style>
body {
margin: 0;
}
html,
body {
height: 100%;
}
header,
footer {
width: 100%;
height: 40px;
position: absolute;
left: 0;
text-align: center;
line-height: 40px;
background: #999999;
color: #ffffff;
z-index: 999;
}
header {
top: 0;
}
footer {
bottom: 0;
}
ul {
display: block;
width: 100%;
position: absolute;
top: 40px;
bottom: 40px;
overflow: auto;
list-style: none;
padding: 0;
margin: 0;
}
ul>li {
width: 100%;
height: 40px;
line-height: 40px;
text-indent: 20px;
border-bottom: 1px solid #666666;
background: #ffffff;
color: #333333;
}
/* 下拉刷新的時候做 */
#loading{
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
color: #333333;
transition: all 0.5s;
position: absolute;
z-index: 1;
color: #ffffff;
background: orange;
top: 0;
}
</style>
</head>
<body>
<header>
我是頭部
</header>
<section id="con">
<div id="loading">加載中......</div>
<ul id="list">
</ul>
</section>
<div id="loadEnd">已加載全部數據</div>
<footer>
我是尾部
</footer>
</body>
<script>
<script>
//獲取數據
var list = document.getElementById("list");
function getData() {
var html = '';
for (var i = 0; i < 20; i++) {
html += '<li>我是第' + (i + 1) + '個li</li>';
}
list.innerHTML = html;
}
//初始加載函數
window.onload = () => {
//初始請求數據
getData();
}
</script>
</script>
</html>
會得到這樣一個網頁,頭部底部固定,中間部分可滑動
接下來,我們來監聽ul的滾動事件
list.addEventListener("scroll", function () {
//這裏可以獲取到ul距離屏幕頂部的距離,每次滾動都會刷新
console.log(this.scrollTop);
})
來做一個分析,接下來不要着急寫代碼
看到這個圖,我們就知道要做什麼了
//ul的高度 不變的 定死的
let listH = list.clientHeight;
//所有li總高度
let contentH = this.childNodes.length * 41;
//差值
let diffValue = contentH - listH;
//距離視窗還有50的時候,開始觸發;
if (this.scrollTop + 50 >= diffValue) {
console.log('該加載了...')
getData();
}
上滑加載完美實現,當我滑到快到最後一個li的時候,觸發獲取數據的方法
我們再添加一個節流閥,不讓它無限加載。
function getData() {
var html = '';
for (var i = 0; i < 20; i++) {
html += '<li>我是第' + (i + 1) + '個li</li>';
}
var length = list.children.length;
if (length === 0) {
list.innerHTML = html;
} else if(length > 0 && length < 100){
//html是字符串
var newHtml = parseDom(html);
//後面插入元素
insertAfter(newHtml, list.children[length - 1]);
}else if(length === 100){
console.log("已經到底了,別拉了");
}
}
這裏有兩個非常重要的方法,都是原生js操作
1.字符串dom化
//字符串dom化
function parseDom(arg) {
var objEle = document.createElement("div");
objEle.innerHTML = arg;
return [...objEle.childNodes];
};
2.在已有元素後面插入元素
//在已有元素後面插入元素
function insertAfter(newElement, targetElement) {
newElement.forEach(element => {
//在後面插入元素 after:js新的dom api
targetElement.after(element)
});
return
}
下拉加載
通過判斷ul的scrollTop值,當ul的scrollTop === 0的時候,觸發
添加到監聽滾動事件裏,加一些樣式操作即可
有些許粗糙,功能爲主,見諒見諒
if(this.scrollTop === 0){
list.style.top = "80px";
loading.style.top = "40px";
//刷新數據
setTimeout(()=>{
loading.style.top = "0";
list.style.top = "40px";
},1000)
}
那麼完整代碼就是
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Document</title>
<style>
body {
margin: 0;
}
html,
body {
height: 100%;
}
header,
footer {
width: 100%;
height: 40px;
position: absolute;
left: 0;
text-align: center;
line-height: 40px;
background: #999999;
color: #ffffff;
z-index: 999;
}
header {
top: 0;
}
footer {
bottom: 0;
}
ul {
display: block;
width: 100%;
position: absolute;
top: 40px;
bottom: 40px;
overflow: auto;
list-style: none;
padding: 0;
margin: 0;
}
ul>li {
width: 100%;
height: 40px;
line-height: 40px;
text-indent: 20px;
border-bottom: 1px solid #666666;
background: #ffffff;
color: #333333;
}
/* 下拉刷新的時候做 */
#loading,#loadEnd{
width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
color: #333333;
transition: all 0.5s;
position: absolute;
z-index: 1;
color: #ffffff;
}
#loading{
background: orange;
top: 0;
}
#loadEnd{
background: green;
bottom: 0;
}
</style>
</head>
<body>
<header>
我是頭部
</header>
<section id="con">
<div id="loading">加載中......</div>
<ul id="list">
</ul>
</section>
<div id="loadEnd">已加載全部數據</div>
<footer>
我是尾部
</footer>
<script>
//獲取數據
var list = document.getElementById("list");
var loading = document.getElementById("loading");
var loadEnd = document.getElementById("loadEnd");
function getData() {
var html = '';
for (var i = 0; i < 20; i++) {
html += '<li>我是第' + (i + 1) + '個li</li>';
}
var length = list.children.length;
if (length === 0) {
list.innerHTML = html;
} else if(length > 0 && length < 100){
//html是字符串
var newHtml = parseDom(html);
//後面插入元素
insertAfter(newHtml, list.children[length - 1]);
}else if(length === 100){
console.log("已經到底了,別拉了");
list.style.bottom = "80px";
loadEnd.style.bottom = "40px";
//加個定時器模擬接口請求結束 隱藏掉此條
//或者可以插入一條元素
}
}
//字符串dom化
function parseDom(arg) {
var objEle = document.createElement("div");
objEle.innerHTML = arg;
return [...objEle.childNodes];
};
//在已有元素後面插入元素
function insertAfter(newElement, targetElement) {
newElement.forEach(element => {
//在後面插入元素 js 新的dom api
targetElement.after(element)
});
return
}
//初始加載函數
window.onload = () => {
//初始請求數據
getData();
list.addEventListener("scroll", function () {
//ul的高度 不變的 定死的
let listH = list.clientHeight;
//所有li總高度
let contentH = this.childNodes.length * 41;
//下拉刷新
if(this.scrollTop === 0){
list.style.top = "80px";
loading.style.top = "40px";
//刷新數據
setTimeout(()=>{
loading.style.top = "0";
list.style.top = "40px";
},1000)
}
//距離
let diffValue = contentH - listH;
//ul離頂部的距離
//距離視窗還有50的時候,開始觸發;
if (this.scrollTop + 50 >= diffValue) {
console.log('該加載了...')
getData();
}
})
}
</script>
</body>
</html>
此篇文章爲作者原創
如需轉載 請註明出處