vue实现下拉刷新组件
Vue 下拉刷新组件实现
基础实现原理
利用触摸事件(touchstart、touchmove、touchend)监听用户手势,结合 CSS 动画实现下拉效果。核心逻辑包括:
- 计算下拉距离与阈值
- 触发刷新回调
- 恢复初始状态
原生实现代码示例
<template>
<div
class="pull-refresh"
@touchstart="onTouchStart"
@touchmove="onTouchMove"
@touchend="onTouchEnd"
>
<div class="refresh-head" :style="{ height: `${headHeight}px` }">
<span v-if="status === 'pulling'">下拉刷新</span>
<span v-else-if="status === 'loosing'">释放刷新</span>
<span v-else-if="status === 'loading'">加载中...</span>
</div>
<slot></slot>
</div>
</template>
<script>
export default {
data() {
return {
startY: 0,
currentY: 0,
headHeight: 0,
status: '', // pulling/loosing/loading
maxHeight: 80
}
},
methods: {
onTouchStart(e) {
this.startY = e.touches[0].pageY
},
onTouchMove(e) {
this.currentY = e.touches[0].pageY
const distance = this.currentY - this.startY
if (distance > 0 && window.scrollY <= 0) {
e.preventDefault()
this.headHeight = Math.min(distance, this.maxHeight)
this.status = distance > this.maxHeight ? 'loosing' : 'pulling'
}
},
onTouchEnd() {
if (this.status === 'loosing') {
this.status = 'loading'
this.headHeight = this.maxHeight
this.$emit('refresh')
} else {
this.headHeight = 0
}
},
finish() {
this.status = ''
this.headHeight = 0
}
}
}
</script>
<style>
.pull-refresh {
position: relative;
overflow: hidden;
}
.refresh-head {
position: absolute;
top: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
transition: height 0.2s;
}
</style>
使用第三方库
推荐使用现成解决方案:
- better-scroll:
import BScroll from '@better-scroll/core' import PullDown from '@better-scroll/pull-down'
BScroll.use(PullDown)
this.scroll = new BScroll('.wrapper', { pullDownRefresh: { threshold: 50, stop: 20 } })
this.scroll.on('pullingDown', () => { fetchData().then(() => { this.scroll.finishPullDown() }) })

2. vant 组件库:
```javascript
<van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<div>内容区域</div>
</van-pull-refresh>
优化方向
- 添加加载动画(旋转图标、进度条等)
- 支持自定义提示文字和样式
- 增加防抖处理避免频繁触发
- 考虑移动端浏览器弹性滚动的影响
注意事项
- 需要确保容器有明确的固定高度
- 在 iOS 上需要额外处理弹性滚动问题
- 列表数据更新后需要手动调用 finish 方法






