You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

187 lines
3.9 KiB

<template>
<view
class="swipe-to-next"
@touchstart="handleTouchStart"
@touchend="handleTouchEnd"
>
<slot></slot>
<!-- 提示文字 -->
<view v-if="showTip && shouldShowTip" class="bottom-tip">
<text>{{ tipText }}</text>
</view>
</view>
</template>
<script>
export default {
name: 'SwipeToNext',
props: {
// 是否在最后一页
isLastSlide: {
type: Boolean,
default: false
},
// 跳转的目标路径
targetPath: {
type: String,
required: true
},
// 是否显示提示文字
showTip: {
type: Boolean,
default: true
},
// 提示文字内容
tipText: {
type: String,
default: '上滑动进入下一章节'
},
// 滑动阈值(px)
swipeThreshold: {
type: Number,
default: 100
},
// 延迟时间(ms)
delayTime: {
type: Number,
default: 500
},
// 是否启用延迟机制
enableDelay: {
type: Boolean,
default: true
},
// 是否总是启用跳转(忽略isLastSlide状态)
alwaysEnable: {
type: Boolean,
default: false
}
},
data() {
return {
touchStartY: 0, // 触摸开始Y坐标
touchEndY: 0, // 触摸结束Y坐标
canJump: false, // 是否允许跳转
delayTimer: null // 延迟定时器
}
},
computed: {
// 是否应该显示提示
shouldShowTip() {
return this.alwaysEnable || this.isLastSlide;
},
// 是否应该允许触摸检测
shouldEnableTouch() {
return this.alwaysEnable || this.isLastSlide;
}
},
watch: {
isLastSlide(newVal) {
this.handleSlideChange(newVal);
},
alwaysEnable: {
handler(newVal) {
if (newVal) {
// 如果启用总是跳转,立即处理
this.handleSlideChange(true);
}
},
immediate: true
}
},
beforeDestroy() {
// 清理定时器
if (this.delayTimer) {
clearTimeout(this.delayTimer);
}
},
methods: {
// 处理滑动状态变化
handleSlideChange(isActive) {
console.log('ppsls');
if (isActive || this.alwaysEnable) {
// 到达最后一页或总是启用
this.canJump = false;
if (this.enableDelay && !this.alwaysEnable) {
// 启用延迟机制(仅当不是总是启用时)
this.delayTimer = setTimeout(() => {
if (this.shouldEnableTouch) {
this.canJump = true;
}
}, this.delayTime);
} else {
// 不启用延迟或总是启用,立即允许跳转
this.canJump = true;
}
} else {
// 离开最后一页且不是总是启用
this.canJump = false;
if (this.delayTimer) {
clearTimeout(this.delayTimer);
this.delayTimer = null;
}
}
},
// 触摸开始
handleTouchStart(e) {
console.log('。。。。。。。。。。///////////');
// 检查是否应该允许触摸
if (this.shouldEnableTouch && (this.canJump || !this.enableDelay || this.alwaysEnable)) {
this.touchStartY = e.touches[0].clientY;
}
},
// 触摸结束
handleTouchEnd(e) {
// 检查是否满足跳转条件
if (!this.shouldEnableTouch || !this.touchStartY) {
return;
}
// 如果启用延迟机制但还不能跳转,且不是总是启用模式,则返回
if (this.enableDelay && !this.canJump && !this.alwaysEnable) {
return;
}
this.touchEndY = e.changedTouches[0].clientY;
const deltaY = this.touchStartY - this.touchEndY;
// 向上滑动且滑动距离大于阈值才跳转
if (deltaY > this.swipeThreshold) {
console.log('向上滑动触发跳转,目标路径:', this.targetPath);
this.$emit('swipe-to-next', this.targetPath);
uni.navigateTo({
url:this.targetPath
});
}
// 重置触摸位置
this.touchStartY = 0;
this.touchEndY = 0;
},
}
}
</script>
<style lang="scss" scoped>
.swipe-to-next {
width: 100%;
height: 100%;
position: relative;
}
.bottom-tip {
position: absolute;
bottom: 50rpx;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.6);
padding: 10rpx 20rpx;
border-radius: 50rpx;
z-index: 999;
text {
color: #fff;
font-size: 24rpx;
}
}
</style>