js实现下拉刷新
实现下拉刷新的基本思路
监听触摸事件,判断用户下拉距离是否达到阈值,触发刷新操作后恢复原位。核心是通过touchstart、touchmove和touchend事件实现交互逻辑。
监听触摸事件
在容器元素上绑定三个触摸事件:
const container = document.getElementById('refreshContainer');
let startY = 0;
let currentY = 0;
container.addEventListener('touchstart', (e) => {
startY = e.touches[0].clientY;
});
container.addEventListener('touchmove', (e) => {
currentY = e.touches[0].clientY;
const distance = currentY - startY;
// 只有向下滑动且内容在顶部时才触发
if (distance > 0 && window.scrollY === 0) {
e.preventDefault();
updateUI(distance);
}
});
container.addEventListener('touchend', () => {
if (currentY - startY > 100) { // 阈值设为100px
triggerRefresh();
}
resetUI();
});
更新UI状态
根据下拉距离动态改变UI元素样式:
function updateUI(distance) {
const maxDistance = 150;
const progress = Math.min(distance / maxDistance, 1);
// 旋转箭头图标
arrowIcon.style.transform = `rotate(${progress * 180}deg)`;
// 控制提示文本
if (distance > 100) {
hintText.textContent = '释放刷新';
} else {
hintText.textContent = '下拉刷新';
}
// 限制最大下拉距离
container.style.transform = `translateY(${Math.min(distance, maxDistance)}px)`;
}
触发刷新与重置
执行刷新操作并恢复初始状态:
function triggerRefresh() {
loadingIcon.style.display = 'block';
arrowIcon.style.display = 'none';
hintText.textContent = '加载中...';
// 模拟异步请求
setTimeout(() => {
refreshData().then(() => {
resetUI();
});
}, 1000);
}
function resetUI() {
container.style.transform = 'translateY(0)';
loadingIcon.style.display = 'none';
arrowIcon.style.display = 'block';
hintText.textContent = '下拉刷新';
startY = 0;
currentY = 0;
}
性能优化建议
使用CSS硬件加速减少卡顿:
#refreshContainer {
will-change: transform;
transition: transform 0.3s cubic-bezier(0.1, 0.7, 0.1, 1);
}
添加防抖处理避免频繁触发:
let isRefreshing = false;
function triggerRefresh() {
if (isRefreshing) return;
isRefreshing = true;
// ...原有逻辑
setTimeout(() => {
refreshData().then(() => {
isRefreshing = false;
resetUI();
});
}, 1000);
}
完整组件示例
创建一个可复用的下拉刷新组件:
class PullToRefresh {
constructor(container, onRefresh) {
this.container = container;
this.onRefresh = onRefresh;
this.init();
}
init() {
this.setupDOM();
this.bindEvents();
}
setupDOM() {
this.container.innerHTML = `
<div class="refresh-control">
<svg class="arrow-icon" viewBox="0 0 24 24">...</svg>
<svg class="loading-icon" viewBox="0 0 24 24">...</svg>
<span class="hint-text">下拉刷新</span>
</div>
<div class="content">${this.container.innerHTML}</div>
`;
}
bindEvents() {
// 事件绑定逻辑...
}
// 其他方法实现...
}
使用时只需初始化:

new PullToRefresh(document.getElementById('list'), fetchNewData);






