vue实现下拉刷新组件
Vue 下拉刷新组件实现
核心思路
通过监听 touch 事件计算滑动距离,结合 CSS 过渡动画实现下拉效果,触发刷新回调。
基础实现步骤
监听 touch 事件
在组件 mounted 阶段绑定 touchstart/touchmove/touchend 事件:
mounted() {
this.$el.addEventListener('touchstart', this.handleTouchStart)
this.$el.addEventListener('touchmove', this.handleTouchMove)
this.$el.addEventListener('touchend', this.handleTouchEnd)
}
计算滑动距离
记录初始 Y 坐标,计算移动距离:
handleTouchStart(e) {
this.startY = e.touches[0].pageY
}
handleTouchMove(e) {
const currentY = e.touches[0].pageY
this.distance = currentY - this.startY
if (this.distance > 0) {
e.preventDefault()
}
}
状态控制
根据距离切换不同状态:
data() {
return {
state: 'waiting', // waiting/pulling/loading
distance: 0,
startY: 0
}
}
动画效果实现
CSS 过渡样式
为下拉区域添加平滑过渡:
.pull-refresh {
transition: transform 0.3s ease;
}
动态位移计算
根据距离动态设置 transform:
get transformStyle() {
return `translateY(${this.distance}px)`
}
阈值判断
设置触发刷新的最小距离(通常 50-80px):

handleTouchEnd() {
if (this.distance > 80) {
this.state = 'loading'
this.$emit('refresh')
} else {
this.reset()
}
}
完整组件示例
模板结构
<template>
<div class="pull-refresh" :style="transformStyle">
<div class="refresh-head">
<span v-if="state === 'loading'">加载中...</span>
<span v-else>下拉刷新</span>
</div>
<slot></slot>
</div>
</template>
状态重置方法
methods: {
reset() {
this.distance = 0
this.state = 'waiting'
},
finishRefresh() {
this.reset()
}
}
优化方向
节流处理
避免 touchmove 事件高频触发:
handleTouchMove: _.throttle(function(e) {
// 计算逻辑
}, 16)
自定义插槽
支持自定义加载动画和提示文案:

<template v-slot:loading>
<custom-spinner />
</template>
弹性效果
实现越界回弹的物理效果:
if (this.distance > 100) {
this.distance = 100 + (this.distance - 100) * 0.5
}
第三方库推荐
-
mescroll.js
支持 Vue 的完整下拉刷新/上拉加载解决方案 -
vue-pull-refresh
轻量级组件,支持自定义动画 -
vant-ui PullRefresh
有赞团队开发的成熟组件
实现时需注意移动端事件兼容性和性能优化,建议使用 passive event listeners 提升滚动性能。






