移动端项目中,下拉刷新和上滑加载是提升用户体验的关键交互。与其依赖第三方库,不如手写一个轻量级组件,既能精准控制逻辑,又能灵活适配业务。今天结合实战经验,聊聊如何用 Vue 实现一个基于 Slot 插槽的通用下拉刷新组件。
组件结构设计
在 components 目录下新建 pullRefreshView 文件夹,创建 index.vue。这个组件的核心思路是:它作为一个容器包裹页面内容,而不是通过遮罩层触发。这样既不影响原有布局,又能通过 Slot 自由插入任何列表或表单。
首先看模板部分,我们需要监听触摸事件,并在底部显示加载状态指示器。
<template>
<div
class="pullRefreshView"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
<!-- 默认插槽,用于包裹实际业务内容 -->
<slot></slot>
<!-- 下拉提示文字 -->
<div class="indicator" v-if="status !== 'loading'">
{{ statusText }}
</div>
<!-- 加载中动画 -->
<div class="indicator loading" v-else>
加载中...
</div>
</div>
</template>
这里有个细节要注意:@touchmove 必须配合 passive: false(在 Vue 中通常由框架处理)来阻止默认滚动行为,否则手指滑动时页面会跟着动,影响体验。不过为了保持代码简洁,我们在逻辑里主要计算位移差。
核心逻辑实现
接下来处理脚本部分,关键在于计算手指下压的距离,并判断是否达到触发阈值。
<script>
export default {
name: 'PullRefreshView',
props: {
// 触发刷新的回调函数
onRefresh: {
type: Function,
required: true
},
// 下拉距离阈值,超过此值触发刷新
threshold: {
type: Number,
default: 80
}
},
data() {
return {
startY: 0, // 触摸起始 Y 坐标
currentY: 0, // 当前 Y 坐标
isDragging: false,// 是否正在拖动
status: ,
:
};
},
: {
() {
(. === ) {
. >= . ? : ;
}
;
}
},
: {
() {
(. > ) ;
. = ;
. = e.[].;
. = ;
},
() {
(!. || . === ) ;
currentY = e.[].;
. = currentY - .;
(. > ) {
. = ;
}
},
() {
(!.) ;
. = ;
(. >= . && . !== ) {
.();
} {
.();
}
},
() {
. = ;
.().( {
.();
}).( {
.();
});
},
() {
. = ;
. = ;
}
}
};
</script>

