上拉加载
上拉加载的本质是
页面触底
,或者快要触底时的动作
触底公式:scrollTop + clientHeight >= scrollHeight
简单实现:
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div id="content">
<!-- Initial content will be loaded here -->
</div>
<script src="./index.mjs" type="module"></script>
</body>
</html>
#content {
height: 80vh;
overflow-y: scroll;
border: 1px solid #ccc;
}
.item {
padding: 20px;
border-bottom: 1px solid #eee;
background: blue;
}
import "./styles.css";
const content = document.getElementById("content");
let page = 1;
// Function to load more content
function loadMore() {
for (let i = 0; i < 10; i++) {
const item = document.createElement("div");
item.className = "item";
item.textContent = `Item ${page * 10 + i + 1}`;
content.appendChild(item);
}
page++;
}
// Initial load
loadMore();
// Event listener for scroll
content.addEventListener("scroll", function () {
let distance = 50; //距离视窗还用50的时候,开始触发;
if (
content.scrollTop + content.clientHeight >=
content.scrollHeight - distance
) {
console.log("加载更多");
loadMore();
}
});
下拉刷新
下拉刷新的本质是页面本身置于顶部时,用户下拉时需要触发的动作
关于下拉刷新的原生实现,主要分成三步:
- 监听原生
touchstart
事件,记录其初始位置的值,e.touches[0].pageY
; - 监听原生
touchmove
事件,记录并计算当前滑动的位置值与初始位置值的差值,大于0
表示向下拉动,并借助CSS3的translateY
属性使元素跟随手势向下滑动对应的差值,同时也应设置一个允许滑动的最大值; - 监听原生
touchend
事件,若此时元素滑动达到最大值,则触发callback
,同时将translateY
重设为0
,元素回到初始位置
简单实现:
import "./styles.css";
const content = document.getElementById("content");
let page = 1;
let loading = false; // 防止重复加载
// Function to load more content
function loadMore() {
if (loading) return; // 防止重复加载
loading = true; // 开始加载
// 模拟网络延迟加载数据
setTimeout(() => {
for (let i = 0; i < 10; i++) {
const item = document.createElement("div");
item.className = "item";
item.textContent = `Item ${page * 10 + i + 1}`;
content.appendChild(item);
}
page++;
loading = false; // 加载完成
}, 1000);
}
// Initial load
loadMore();
// Variables to handle pull down
let _refreshText = document.querySelector(".refreshText");
let startY = 0;
let _transitionHeight = 0;
let isPulling = false;
// Function to refresh content
function refresh() {
console.log("refresh");
content.innerHTML = ""; // 清空内容
page = 1; // 重置页码
loadMore(); // 重新加载内容
_refreshText.innerText = "下拉刷新"; // 恢复提示文本
}
// Touch event listeners for pull down refresh
content.addEventListener("touchstart", function (event) {
if (content.scrollTop === 0) {
startY = event.touches[0].pageY; // 记录初始位置
content.style.position = "relative";
content.style.transition = "transform 0s";
isPulling = true;
}
});
content.addEventListener("touchmove", function (event) {
if (isPulling) {
_transitionHeight = event.touches[0].pageY - startY; // 计算下拉距离
if (_transitionHeight > 0) {
content.style.transform = "translateY(" + _transitionHeight + "px)";
_refreshText.innerText = _transitionHeight > 55 ? "释放更新" : "下拉刷新";
}
}
});
content.addEventListener("touchend", function () {
if (_transitionHeight > 55) {
_refreshText.innerText = "正在更新..."; // 更新提示文本
refresh(); // 下拉超过阈值,触发刷新
} else {
_refreshText.innerText = "下拉刷新"; // 恢复提示文本
}
// 复位视图
content.style.transition = "transform 0.5s ease";
content.style.transform = "translateY(0px)";
isPulling = false; // 结束下拉状态
});
// Event listener for scroll (for loading more)
content.addEventListener("scroll", function () {
if (content.scrollTop + content.clientHeight >= content.scrollHeight) {
loadMore(); // 触发加载更多内容
}
});