首先下拉刷新功能就是为了让用户拿到最新的内容,提高用户体验。 实现思路:监听用户的在屏幕上的操作,用touchstart监听用户手指触摸屏幕, touchmove监听用户手指滑动, touchend监听用户手指离开屏幕。
先进行布局 Pull.vue
<div class="pull" ref="pull">
<div class="pull-top" ref="pullTop">
<div class="loading" ref="span">
</div>
</div>
<div class="pull-box">
</div>
</div>
css样式布局
.pull {
width: 100vw;
.pull-top {
width: 100vw;
background-color: hotpink;
.loading {
text-align: center;
}
}
.pull-box {
width: 100vw;
height: 100vh;
background-color: skyblue;
}
}
创建一个Pull.ts文件( .ts文件名与.vue的文件名要一致)
在pull.ts文件中首先需要获取最大的盒子pull ,在获取第一个子盒子 pullTop
const pull = ref<HTMLDivElement>()
const pullTop = ref<HTMLDivElement>()
const span = ref<HTMLDivElement>()
onMounted里面首先在touchstart中获取用户手指在屏幕上 的初始位置(使用 e.changedTouches[0].pageY,将这个初始值保存起来 (disY) ,同时还需要清除过渡,将transition为nonoe,其次在touchmove事件里获取手指的移动位置(e.changedTouches[0].pageY) ,用这个值减去初始值,就是用户滑动的距离,将这个值保存起来(Y),然后在把这个值(Y)赋给下拉刷新的盒子的高然后在手指离开的时候,判断一下下拉的距离是否大于等于60如果要是符合条件,就把这个Y设置为40,然后再设置一个定时器让他在1秒以后让这个值(Y)设置为0;然后再将这个(Y)的设置为下拉刷新盒子的高度;然后还要让他阻尼,阻尼的时候在(touchmove )的时候去设置,刚开始的时候先在(onMounted)获取整个屏幕的可视区的高度,然后让这个高度 / 150;这个150也就是超过150阻尼的效果才会明显,然后在将原来的Y值 / 阻尼的结果 赋值给下拉刷新盒子的高度,然后还要设置一个过渡的效果在(touchend)的时候设置一下transition,然后在让刚开始的时候要清空一下transition 然后还要解除绑定事件,touchmove和touchend设置为null。下拉的时候会把整个页面拉下来 所以要设置一下阻止默认事件用 ev.preventDefault && ev.preventDefault()
完整的Pull.vue代码
<template>
<div class="pull" ref="pull">
<div class="pull-top" ref="pullTop">
<div class="loading" ref="span">
</div>
</div>
<div class="pull-box">
</div>
</div>
</template>
<script setup lang="ts">
import { pulldownStore } from '@/store/Pull'
import { storeToRefs } from 'pinia'
const LoginStore = pulldownStore()
const { pull, pullTop, span } = storeToRefs(LoginStore)
const { } = LoginStore
</script>
<style scoped lang="less">
.pull {
width: 100vw;
.pull-top {
width: 100vw;
background-color: hotpink;
overflow: hidden;
.loading {
text-align: center;
}
}
.pull-box {
width: 100vw;
height: 100vh;
background-color: skyblue;
}
}
</style>
完整的Pull.ts的代码
import { defineStore } from 'pinia'
import { ref, onMounted } from 'vue'
export const pulldownStore = defineStore('pull', () => {
const Position = {
disY: 0,
Y: 0,
height: 0,
timer: 0,
scale: 0,
}
const pull = ref<HTMLDivElement>()
const pullTop = ref<HTMLDivElement>()
const span = ref<HTMLDivElement>()
const FnStart = (e: TouchEvent) => {
pullTop.value!.style.transition = 'none'
Position.disY = e.changedTouches[0].pageY - Position.Y
document.ontouchmove = FnMove
document.ontouchend = FnEnd
}
const FnMove = (e: TouchEvent) => {
if (Position.Y > 35) {
span.value!.textContent = '下拉刷新'
}
if (Position.Y > 60) {
span.value!.textContent = '释放刷新'
}
Position.Y = e.changedTouches[0].pageY - Position.disY
Position.scale = Position.height / 150
Position.Y = Position.Y / Position.scale
pullTop.value!.style.height = Position.Y + 'px'
}
const FnEnd = () => {
clearTimeout(Position.timer)
pullTop.value!.style.transition = `.3s ease-in height`
if (Position.Y >= 60) {
span.value!.textContent = '刷新中'
Position.Y = 40
Position.timer = setTimeout(() => {
Position.Y = 0
pullTop.value!.style.height = Position.Y + 'px'
span.value!.textContent = '刷新成功'
}, 1000)
} else {
span.value!.textContent = ''
Position.Y = 0
}
pullTop.value!.style.height = Position.Y + 'px'
}
onMounted(() => {
pull.value!.ontouchstart = FnStart
Position.height = document.documentElement.clientHeight
})
return {
pull,
pullTop,
span
}
})