vue实现下拉刷新组件
实现下拉刷新组件的核心思路
下拉刷新功能通常通过监听触摸事件、滚动位置和动画效果实现。Vue中可以利用自定义指令或封装组件完成,以下为两种常见实现方式。
基于自定义指令的实现
创建指令监听触摸事件,计算下拉距离并触发回调:
Vue.directive('pull-to-refresh', {
bind(el, binding) {
let startY = 0
let currentY = 0
const refreshHeight = 50
el.addEventListener('touchstart', e => {
startY = e.touches[0].pageY
}, { passive: true })
el.addEventListener('touchmove', e => {
currentY = e.touches[0].pageY
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
if (scrollTop === 0 && currentY - startY > 0) {
e.preventDefault()
const distance = Math.min(currentY - startY, refreshHeight * 3)
binding.value(distance / refreshHeight)
}
}, { passive: false })
el.addEventListener('touchend', () => {
if ((currentY - startY) > refreshHeight) {
binding.value('refresh')
} else {
binding.value(0)
}
}, { passive: true })
}
})
使用方式:
<div v-pull-to-refresh="handleRefresh">
<!-- 内容区域 -->
</div>
封装可复用组件方案
创建独立组件处理所有交互逻辑:
<template>
<div class="refresh-container" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd">
<div class="refresh-control" :style="{ transform: `translateY(${pullDistance}px)` }">
<slot name="loading" v-if="isRefreshing">
<!-- 自定义加载中状态 -->
</slot>
<slot name="pull" v-else>
<!-- 自定义下拉提示 -->
</slot>
</div>
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
startY: 0,
currentY: 0,
pullDistance: 0,
isRefreshing: false,
maxPullDistance: 70
}
},
methods: {
onTouchStart(e) {
if (this.isRefreshing) return
this.startY = e.touches[0].pageY
},
onTouchMove(e) {
if (this.isRefreshing) return
this.currentY = e.touches[0].pageY
const scrollTop = document.documentElement.scrollTop
if (scrollTop === 0 && this.currentY - this.startY > 0) {
this.pullDistance = Math.min(
this.currentY - this.startY,
this.maxPullDistance
)
}
},
onTouchEnd() {
if (this.pullDistance > this.maxPullDistance * 0.6) {
this.isRefreshing = true
this.$emit('refresh')
} else {
this.pullDistance = 0
}
},
finishRefresh() {
this.isRefreshing = false
this.pullDistance = 0
}
}
}
</script>
<style>
.refresh-container {
position: relative;
}
.refresh-control {
position: absolute;
width: 100%;
top: 0;
left: 0;
transition: transform 0.3s ease;
}
</style>
第三方库推荐方案
-
vue-pull-refresh
安装:npm install vue-pull-refresh使用示例:
<template> <pull-refresh @refresh="onRefresh"> <!-- 内容区域 --> </pull-refresh> </template> <script> import PullRefresh from 'vue-pull-refresh' export default { components: { PullRefresh }, methods: { onRefresh(done) { fetchData().then(() => done()) } } } </script> -
mescroll.js
支持下拉刷新和上拉加载的完整解决方案:<template> <mescroll-vue ref="mescroll" @down="downCallback" @up="upCallback"> <!-- 内容列表 --> </mescroll-vue> </template>
性能优化要点
-
使用CSS
will-change属性提升动画性能:.refresh-control { will-change: transform; } -
避免频繁的DOM操作,使用transform代替top定位
-
添加防抖处理快速连续触发
-
移动端注意
passive事件监听器的使用







