14.移动端如何实现上拉加载下拉刷新

在移动端长列表,需要通过上拉加载提升性能

1. 上拉加载

主要目的是为了提升性能

  1. 处理滚动事件监听
  2. 怎么判断触底
  3. 回调触发列表加载更多
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<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.items.forEach(item=>{
						const div=document.createElement('div')
						div.className='item'
						div.textContent=item.text
						list.appendChild(div)
					})
				})
			}
			
			function handleScroll(){
				if(list.scrollTop + list.clientHeight >=list.scrollHeight-10){
					page++
					loadMoreData()
				}
			}
			
			list.addEventListener('scroll',handleScroll)
			
			loadMoreData(page)
		</script>
	</body>
</html>

2. 下拉刷新

用户在页面顶部向下拉时,触发页面重新渲染

  1. 监听触摸事件,touch、top
  2. 显示刷新指示器,显示有没有达到下拉阈值
  3. 触发刷新操作
<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<div id='refreshIndicator'></div>
		<div id="list"></div>
		<script>
			const list = document.getElementById('list')
			const refreshIndicator = document.getElementById('refreshIndicator')
			let startY = 0
			let isPulling = false

			function loadMoreData(page) {
				return fetch(`https://example.com/api/data?page=${page}`)
					.then(response => response.json())
					.then(data => {
							list.innerHTML = ''
							data.item.forEach(item => {
								const div = document.createElement('div')
								div.className = 'item'
								div.textContent = item.text
								list.appendChild(div)
							})
							refreshIndicator.style.display='none'
						}
					}

				list.addEventListener('touchstart',event=>{
						
					if(list.scrollTop === 0){
						startY=event.touches[0].pageY
						isPulling=true
					}
				})
				
				list.addEventListener('touchmove',event=>{
					if(isPulling){
						const currentY=event.touches[0].pageY
						if(currentY>startY){
							refreshIndicator.style.display='block'
							refreshIndicator.style.height=`${currentY -startY}px`
						}
					}
				})
				
				list.addEventListener('touchend',()=>{
					if(isPulling){
						const refreshHeight=parseInt(refreshIndicator.style.height,10)
						if(refreshHeight>50){
							loadData()
						}else{
							refreshIndicator.style.display='none'
						}
						isPulling=false
						refreshIndicator.style.height='50px'
					}
				})

				loadMoreData(page)
		</script>
	</body>
</html>

3. 考虑的点

3.1 性能优化

  1. 节流、防抖
  2. 懒加载

3.2 用户体验

  1. 视觉反馈、下拉刷新的指示器
  2. 平滑动画
  3. 错误处理

3.3 兼容性

  1. 触摸事件兼容性
  2. css hook