Appearance
移动端上拉加载、下拉刷新实现方案
上拉加载
长列表,需要通过上拉加载提示性能
实现步骤
- 滚动事件监听
- 怎么判断触底
- 回调触发列表加载更多
html
<div id="list"></div>
<script>
const list = document.getElementById('list')
let page = 1
function loadMoreData(page) {
return fetch(`https://example.com/api/data?page=${page}`)
.then((response) => response.json())
.then((data) => {
data.forEach((item) => {
const li = document.createElement('li')
li.textContent = item.name
list.appendChild(li)
})
})
}
function handleScroll() {
// 触底距离:10
if (list.scrollTop + list.clientHeight >= list.scrollHeight - 10) {
page++
loadMoreData(page)
}
}
list.addEventListener('scroll', handleScroll)
// 初始化数据
loadMoreData(page)
</script>
下拉刷新
在用户页面顶部向下拉时,触发页面刷新,重新渲染
实现步骤
- 监听触摸事件,touch、tap
- 显示刷新指示器,显示有没有达到下拉阈值
- 触发刷新操作
html
<div id="list">
<div id="refreshIndicator"></div>
</div>
<script>
const list = document.getElementById('list')
const refreshIndicator = document.getElementById('refreshIndicator')
let startY = 0
let isPulling = false
function loadData() {
return fetch(`https://example.com/api/data`)
.then((response) => response.json())
.then((data) => {
list.innerHTML = '' // 清空现有数据
data.forEach((item) => {
const li = document.createElement('li')
li.textContent = item.name
list.appendChild(li)
})
refreshIndicator.style.display = 'none' // 隐藏刷新指示器
})
}
list.addEventListener('touchstart', (e) => {
if (list.scrollTop === 0) {
startY = e.touches[0].clientY
isPulling = true
}
})
list.addEventListener('touchmove', (e) => {
if (isPulling) {
const currentY = e.touches[0].pageY
if (currentY > startY) {
{
refreshIndicator.style.display = 'block'
refreshIndicator.style.height = `${currentY - startY}px`
}
}
}
})
list.addEventListener('touchend', (e) => {
if (isPulling) {
const refreshHeight = parseInt(refreshIndicator.style.height, 10)
if (refreshHeight >= 50) {
loadData()
} else {
refreshIndicator.style.display = 'none'
}
isPulling = false
refreshIndicator.style.height = '50px'
}
})
loadData()
</script>
考虑的点
性能优化
- 节流防抖
- 懒加载
用户体验
- 视觉反馈,下拉刷新指示器
- 平滑动画
- 错误处理
兼容
- 触摸事件
- css hack (css 兼容)