前言
前几天在捣鼓我那 H5 应用,之前打算不依赖组件库,所以把移动端相关的一些功能实现了,在此记录一下实现下拉刷新的过程。
实现原理
一图以蔽之:
简要概述:
- 下拉触发
- 手势释放时小于最小触发阈值
minConditionH,直接回弹 - 否则容器设置偏移,并成功触发下拉
- 偏移大于最大偏移阈值
maxConfitionH,则容器不再偏移 - 触发下拉成功后,请求数据,数据请求成功,则显示成功文案,否则显示失败文案,并在一秒后回弹
代码实现
下拉 DOM 结构,采用 unocss 设置样式
<div
ref="container"
class="relative h-full"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<div class="absolute w-full center text-color -translate-y-100%">
{{ text }}
</div>
<div class="h-full overflow-y-auto">
<div v-for="(item, index) in list" :key="index">
{{ item }}
</div>
</div>
</div>
下拉事件处理程序
const list = ref(Array.from({ length: 1000 }, (_, index) => index))
// 开始下来位置
let startY = 0
// 下拉偏移量
let offsetY = 0
// 大于 minConditionH 才算触发下拉刷新
const minConditionH = 40
// 大于 maxConfitionH 则不做容器偏移
const maxConfitionH = 100
const text = ref('下拉刷新')
const container = ref()
function touchstart(evt: TouchEvent) {
if (container.value.scrollTop === 0) {
startY = evt.touches[0].pageY
text.value = '下拉即可刷新'
}
}
function touchmove(evt: TouchEvent) {
const currentPosition = evt.touches[0].pageY
offsetY = currentPosition - startY
if (offsetY > minConditionH)
text.value = '释放刷新'
else
text.value = '下拉即可刷新'
// 限制下拉差值为 maxConfitionH,大于这个不再进行偏移
if (offsetY < maxConfitionH) {
container.value.style.transition = 'transform 0s'
container.value.style.transform = `translateY(${offsetY}px)`
}
}
function touchend() {
// 如果下拉差值小于最小触发阈值,则回弹
if (offsetY >= 0 && offsetY <= minConditionH) {
container.value.style.transition = 'transform 1s'
container.value.style.transform = 'translateY(0px)'
offsetY = 0
return
}
if (offsetY > 40) {
// 下拉差值大于 最小阈值,则触发刷新
container.value.style.transform = 'translateY(40px)'
container.value.style.transition = 'transform 0.5s'
text.value = '刷新中...'
// 请求数据,现模拟
setTimeout(() => {
// 请求成功,则显示成功
text.value = '刷新成功'
// 先停留1s,再返回最初状态
setTimeout(() => {
container.value.style.transition = 'transform 0.5s'
container.value.style.transform = 'translateY(0px)'
}, 1000)
}, 2000)
}
// 下拉结束后重置差值
offsetY = 0
}
在线体验
加载更多
利用 composables api 可以非常方便的实现加载更多
import { debounce } from 'lodash-es'
export function useLoadMore(el: HTMLElement, cb: () => void) {
useEventListener(el, 'scroll', debounce(() => {
const clientHeight = el.clientHeight
const scrollTop = el.scrollTop
const scrollHeight = el.scrollHeight
const top = Math.ceil(clientHeight + scrollTop)
if (top >= scrollHeight)
cb()
}, 500, { leading: true }))
}
总结
本篇介绍了移动端的 下拉刷新 和 加载更多 实现,接下来继续介绍移动端基本组件实现,欢迎关注!