先创建一个vue文件然后在布局
<div class="pull" ref="pull"> <div class="pull-top" ref="pullTop">{{ text }}</div> <div class="pull-content"></div> </div>
CSS样式
.pull { width: 100vw; .pull-top { width: 100vw; // height: 100px; background-color: aquamarine; text-align: center; } .pull-content { width: 100vw; height: 100vh; background-color: coral; } }
思路如下:
然后在创建一个.ts文件,文件名与vue的文件名一致
首先,先获取要展示下拉刷新的那个div,然后在获取整个div,使用ref获取 然后在页面加载完成后绑定三个事件 touchstart 用户手指触摸屏幕 ,touchmove :用户手指滑动 ,touchend:用户手指离开 ,在onMounted中写
首先用户在触摸屏幕的时候(touchstart ) 先获取用户触摸屏幕的位置(ev.changedTouches[0].pageY),然后把他保存起来(disY),然后用户下拉的时候(touchmove )获取手指的移动位置(ev.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">{{ text }}</div>
<div class="pull-content"></div>
</div>
</template>
<script setup lang="ts">
import { usePullStore } from '@/store/Pull'
import { storeToRefs } from 'pinia'
const PullStore = usePullStore()
const { pull, pullTop, text } = storeToRefs(PullStore)
const {} = PullStore
</script>
<style scoped lang="less">
.pull {
width: 100vw;
.pull-top {
width: 100vw;
// height: 100px;
background-color: aquamarine;
text-align: center;
overflow: hidden;
}
.pull-content {
width: 100vw;
height: 100vh;
background-color: coral;
}
}
</style>
Pull.ts
import { defineStore } from "pinia";
import { ref, onMounted } from 'vue'
export const usePullStore = defineStore('Pull', () => {
const pull = ref<HTMLDivElement>()
const pullTop = ref<HTMLDivElement>()
const text = ref<string>('')
const positions = {
disY: 0,
Y: 0,
height: 0,
scale: 0,
timer: 0,
}
const FnMove = (ev: TouchEvent) => {
if (positions.Y > 1) {
text.value = '下拉刷新'
}
if (positions.Y > 60) {
text.value = '释放更新'
}
positions.Y = ev.changedTouches[0].pageY - positions.disY
positions.scale = positions.height / 150
positions.Y = positions.Y / positions.scale
pullTop.value!.style.height = positions.Y + 'px'
}
const FnEnd = () => {
clearTimeout(positions.timer)
pullTop.value!.style.transition = `.3s ease-in height`
if (positions.Y >= 60) {
positions.Y = 40
text.value = '更新中...'
positions.timer = setTimeout(() => {
text.value = '刷新成功 '
setTimeout(() => {
positions.Y = 0
pullTop.value!.style.height = positions.Y + 'px'
}, 500)
}, 1000)
} else {
positions.Y = 0
}
pullTop.value!.style.height = positions.Y + 'px'
}
const FnStart = (ev: TouchEvent) => {
pullTop.value!.style.transition = `none`
positions.disY = ev.changedTouches[0].pageY - positions.Y
document.ontouchmove = FnMove
document.ontouchend = FnEnd
ev.preventDefault && ev.preventDefault()
}
onMounted(() => {
pull.value!.ontouchstart = FnStart
positions.height = document.documentElement.clientHeight
})
return {
pull,
pullTop,
text
}
})