JavaScript 下拉/上拉刷新

在这里插入图片描述

<!DOCTYPE html> 
<html lang="zh-cn">
<head> 
<meta charset="UTF-8"> 
<title>Pull to Refresh</title>
<style>
* {
	margin: 0;
	padding: 0;
}
.scroll-container {
	position: relative;
	/** 拖动到最下面的时候滚动条会突然消失,造成页面resize,所以通过overflow隐藏滚动条 */
	overflow-y: hidden;
	/** height不能设置为100%,因为它是根据内容而定的,而100vh表示浏览器满高度 */
	height: 100vh;
}
.scroll-container>ul {
	list-style: none;
	text-align: center;
	line-height: 300%;
	color: white;
	position: absolute;
	width: 100%;
	background-color: #999;
}
.scroll-container>ul>li {
	border: 1px solid white;
}
.scroll-container>div:first-child, .scroll-container>div:last-child {
	justify-content: center;
	align-items: center;
	color: black;
	background-color: red;
	position: absolute;
	/** absolute的元素,如果不设置宽度,即使是block的也会变成wrap_content */
	width: 100%;
	overflow-y: hidden;
}
</style> 
<script>
function fullData(count, type) {
	console.log("refreshType: " + type);
	const container = document.querySelector(".scroll-container>ul");
	for(let i=0; i<count; i++) {
		const node = document.createElement("li");
		node.textContent = "第 " + container.children.length + " 条测试数据";
		container.appendChild(node);
	}
}
class PullToRefresh {
	constructor(scrollContainer, callback) {
		const container = scrollContainer.firstElementChild;
		const contentBefore = document.createElement("div");
		const contentEnd = document.createElement("div");
		scrollContainer.insertBefore(contentBefore, scrollContainer.firstChild);
		scrollContainer.appendChild(contentEnd);
		
		this.container = container;
		container.tips = ["Pull Down To Refresh", "Pull Up To Refresh", "Release To Refresh", "Loading...", "All Data Has Been Loaded"];
		//拉伸出多大的空间说明刷新有效
		container.effectDistance = 80;
		//拉伸出的空间的极限值
		container.tensileLimit = 100;
		//0表示不刷新,1表示下拉刷新,2表示上拉刷新
		container.refreshType = 0;
		//每次滚动的距离
		container.scrollStep = 20;
		container.pullToRefreshCallback = callback;
		container.siblingPrev = contentBefore;
		container.siblingNext = contentEnd;
		this.setListener(container);
	}
	setListener(container) {
		container.addEventListener('touchstart', this.touchStart, false);
		container.addEventListener('touchmove', this.touchMove, false);
		container.addEventListener('touchend', this.touchEndFunc, false);
		container.addEventListener('mousedown', this.touchStart, false);
		container.addEventListener('mousemove', this.touchMove, false);
		container.addEventListener('mouseup', this.touchEnd, false);
		//火狐使用DOMMouseScroll,其它浏览器使用mousewheel事件
		container.addEventListener("DOMMouseScroll", this.scroll, false);
		container.onmousewheel = this.scroll;
	}
	touchStart(event) {
		/*
		event.button
		其它浏览器:0鼠标左键;1鼠标中键;2鼠标右键
		IE浏览器: 1鼠标左键;4鼠标中键;2鼠标右键
		*/
		if(event.button === 0) {
			const container = event.currentTarget;
			container.isTouch = true;
			container.startY = event.y;
			container.startTop = container.offsetTop;
			container.refreshType = 0;
		}
	}
	touchMove(event) {
		const container = event.currentTarget;
		if(event.button === 0 && container.isTouch) {
			//从鼠标左键按下的点开始计算的下拉的距离
			const diff = event.y - container.startY;
			//容器与页面左上角的相对位移
			const containerTop = container.startTop + diff;
			if(diff > 0) {
				//下拉
				if(containerTop > container.tensileLimit) {
					return;
				} else if(containerTop > container.effectDistance) {
					container.siblingPrev.textContent = container.tips[2];
					container.siblingPrev.style.height = containerTop + "px";
					container.refreshType = 1;
				} else if(containerTop > 0) {
					container.siblingPrev.textContent = container.tips[0];
					container.siblingPrev.style.display = "flex";
					container.siblingPrev.style.height = containerTop + "px";
					container.refreshType = 0;
				} else {
					container.siblingPrev.style.display = "none";
					container.refreshType = 0;
				}
				container.style.top = containerTop + "px";
				container.siblingNext.style.display = "none";
			} else {
				//上拉
				/*
				container.clientHeight这个是容器完整的高度(包括不可见部分)
				document.documentElement.clientHeight这个是窗口实际高度
				*/
				//超出屏幕可见区域的高度值(正数)
				const exceedHeight = container.clientHeight - document.documentElement.clientHeight;
				//下面这个逻辑有点复杂,可以先分开写,然后寻找共同点并合并
				/*
				if(exceedHeight < 0) {
					//小于0表示内容未填满整个窗口
					if(containerTop + container.tensileLimit < 0) {
						return;
					} else if(containerTop + container.effectDistance < 0) {
						container.siblingNext.textContent = container.tips[2];
						container.siblingNext.style.height = -containerTop + "px";
						container.siblingNext.style.top = containerTop + container.clientHeight + "px";
						container.refreshType = 2;
					} else if(containerTop < 0) {
						container.siblingNext.textContent = container.tips[1];
						container.siblingNext.style.display = "flex";
						container.siblingNext.style.height = -containerTop + "px";
						container.siblingNext.style.top = containerTop + container.clientHeight + "px";
						container.refreshType = 0;
					} else {
						container.siblingNext.style.display = "none";
						container.refreshType = 0;
					}
				} else {
					if(containerTop + exceedHeight + container.tensileLimit < 0) {
						return;
					} else if(containerTop + exceedHeight + container.effectDistance < 0) {
						container.siblingNext.textContent = container.tips[2];
						container.siblingNext.style.height = containerTop + exceedHeight + "px";
						container.siblingNext.style.top = containerTop + container.clientHeight + "px";
						container.refreshType = 2;
					} else if(containerTop + exceedHeight < 0) {
						container.siblingNext.textContent = container.tips[1];
						container.siblingNext.style.display = "flex";
						container.siblingNext.style.height = containerTop + exceedHeight + "px";
						container.siblingNext.style.top = containerTop + container.clientHeight + "px";
						container.refreshType = 0;
					} else {
						container.siblingNext.style.display = "none";
						container.refreshType = 0;
					}
				}
				*/
				const tmpExceedHeight = exceedHeight < 0 ? 0 : exceedHeight;
				if(containerTop + tmpExceedHeight + container.tensileLimit < 0) {
					return;
				} else if(containerTop + tmpExceedHeight + container.effectDistance < 0) {
					container.siblingNext.textContent = container.tips[2];
					container.siblingNext.style.height = -containerTop - exceedHeight + "px";
					container.siblingNext.style.top = containerTop + container.clientHeight + "px";
					container.refreshType = 2;
				} else if(containerTop + tmpExceedHeight < 0) {
					container.siblingNext.textContent = container.tips[1];
					container.siblingNext.style.display = "flex";
					container.siblingNext.style.height = -containerTop - exceedHeight + "px";
					container.siblingNext.style.top = containerTop + container.clientHeight + "px";
					container.refreshType = 0;
				} else {
					container.siblingNext.style.display = "none";
					container.refreshType = 0;
				}
				
				container.style.top = containerTop + "px";
				container.siblingPrev.style.display = "none";
			}
		}
	}
	touchEnd(event) {
		if(event.button == 0) {
			const container = event.currentTarget;
			container.isTouch = false;
			if(container.offsetTop > 0) {
				container.style.top = "0";
			} else {
				const containerTop = container.clientHeight - document.documentElement.clientHeight;
				if(containerTop < 0) {
					//内容未填满整个窗口
					container.style.top = "0";
				} else if(container.offsetTop + containerTop < 0) {
					container.style.top = -containerTop + "px";
				}
			}
			container.siblingPrev.style.display = "none";
			container.siblingNext.style.display = "none";
			if(container.refreshType != 0) {
				container.pullToRefreshCallback(container.refreshType);
			}
		}
	}
	scroll(event) {
		const container = event.currentTarget;
		const containerTop = container.clientHeight - document.documentElement.clientHeight;
		if(containerTop < 0 || container.isTouch) {
			//小于0表示内容未填满整个窗口
			return;
		}
		const minTop = document.documentElement.clientHeight - container.clientHeight;
		let top = 0;
		//firefox用的是event.detail,+3表示为向下滚动,-3表示向上滚动;其它浏览器用的是wheelDelta,+120表示向上,-120表示向下
		if((event.detail && event.detail > 0) || (event.wheelDelta && event.wheelDelta < 0)) {
			top = container.offsetTop - container.scrollStep;
		} else {
			top = container.offsetTop + container.scrollStep;
		}
		top = Math.min(0, Math.max(minTop, top));
		container.style.top = top + "px";
	}
}
window.onload = ()=>{
	fullData(5, 0);
	const scrollContainer = document.querySelector('.scroll-container');
	new PullToRefresh(scrollContainer, (type)=>fullData(5, type));
}
</script>
</head>
<body>
<div class="scroll-container"><ul></ul></div>
</body> 
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值