下拉刷新主要用于移动端网页,PC端网页并没有 touch 事件所以需要自行模拟。实现该功能主要依赖如下几个事件:
- touchstart
- touchmove
- touchend
从事件名我们很容易就能看出这几个事件分别代表什么含义。在事件回调函数里面,可以获取 touchList,该 list 中的每一个元素表示一个触摸点的信息。可以看出,触摸事件可以监听到多个触摸点,例如多个手指滑动屏幕就会有多个触摸点。实现下来刷新功能,我们只考虑一个触摸点即可。
思路
下拉刷新的思路很简单:
- 触摸开始时保存初始触摸点在屏幕上的坐标
- 触摸移动时计算移动的触摸点和初始坐标点的距离,如果距离大于阈值,则触发刷新回调
- 触摸结束后重置触摸状态
值得注意的是,在 touchmove 的时候,计算下拉距离的同时也要显示下拉加载提示元素,具体思路就是设置提示元素的 min-height
,设置 min-height 使动画生效。
<html>
<head>
<title>Pulldown refresh</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<style>
body {
margin: 0;
background-color: #eee;
}
#tip-wrap {
height: 0;
overflow: hidden;
text-align: center;
background-color: #ccc;
font-size: 0.9rem;
color: white;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
pointer-events: none;
transition: min-height 0.2s ease;
}
</style>
</head>
<body>
<div id="tip-wrap">
<div id="tip">松开刷新</div>
</div>
<div id="wrap">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Similique delectus dolores dolore commodi minus,
corrupti, veritatis totam repudiandae facilis dolorum beatae labore nesciunt vel fugit illum quo distinctio
praesentium accusamus.
</div>
<script>
let state = undefined // start | moving | end
let touchStartY = undefined;
let touchTrigger = 100;
let dist = 0
const tip = document.querySelector('#tip-wrap')
const tipmsg = document.querySelector('#tip')
const wrap = document.querySelector('#wrap')
window.addEventListener('touchstart', (e) => {
console.log('touchstart', e.touches)
if (!window.scrollY)
touchStartY = e.touches[0].screenY;
state = 'start'
}, false)
window.addEventListener('touchmove', (e) => {
// ('touchmove', )
const screenY = e.touches[0].screenY
if (state === 'start') {
touchStartY = screenY
state = 'moving'
}
dist = screenY - touchStartY
if (dist > 0) {
e.preventDefault();
tip.style.minHeight = Math.min(dist, 50) + 'px'
}
}, { passive: false })
window.addEventListener('touchend', (e) => {
console.log('touchend', e.touches)
if(dist >= 50 && !window.scrollY) {
alert('refresh')
}
touchStartY = 0
tip.style.minHeight = 0
}, false)
</script>
</body>
</html>
注意addEventListener('touchmove', cb, { passive: false })
, { passive: false }
能达到下拉页面时页面不会整体向下移动的效果。