refactor(todo): 替换滑动触发加载为点击加载更多
重构了待办页面的加载更多逻辑:移除滚动监听和自动加载逻辑,改为点击按钮触发加载;优化了加载状态提示和UI样式,简化了滚动视图高度计算逻辑,移除了多余的状态变量和防抖冷却逻辑。
This commit is contained in:
@@ -37,8 +37,6 @@
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
@scroll="onScroll"
|
||||
lower-threshold="100"
|
||||
>
|
||||
<!-- 待贴标签列表 -->
|
||||
<view v-if="activeTab === 'label'" class="coil-list">
|
||||
@@ -69,18 +67,21 @@
|
||||
<uni-load-more status="loading" />
|
||||
</view>
|
||||
|
||||
<!-- 加载更多提示 -->
|
||||
<view v-if="activeTab === 'label' && list.length > 0 && list.length < total" class="load-more-wrapper">
|
||||
<view v-if="isAtBottom && canLoadMore" class="bottom-hint">
|
||||
<text class="hint-text">↑ 向上滑动加载更多</text>
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="activeTab === 'label' && list.length > 0 && list.length < total" class="load-more-wrapper" @click="onLoadMore">
|
||||
<view v-if="loading" class="load-more-loading">
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
<view v-else @click="onLoadMore">
|
||||
<uni-load-more
|
||||
:status="loadMoreStatus"
|
||||
:content-text="{ contentdown: '点击加载更多', contentrefresh: '加载中...', contentnomore: '没有更多了' }"
|
||||
/>
|
||||
<view v-else class="load-more-btn">
|
||||
<text class="btn-text">点击加载更多</text>
|
||||
<text class="btn-hint">(已加载 {{ list.length }} / {{ total }} 条)</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 已加载全部 -->
|
||||
<view v-if="activeTab === 'label' && list.length > 0 && list.length >= total" class="load-more-wrapper no-more">
|
||||
<text class="no-more-text">已加载全部 {{ total }} 条数据</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 记录弹窗 -->
|
||||
@@ -119,10 +120,6 @@ export default {
|
||||
list: [],
|
||||
loading: false,
|
||||
refreshing: false,
|
||||
loadMoreCooldown: false, // 加载更多冷却期标志
|
||||
isAtBottom: false, // 是否滑动到底部
|
||||
canLoadMore: false, // 是否可以加载更多(需要再次向上滑动)
|
||||
lastScrollTop: 0, // 上次滚动位置
|
||||
query: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
@@ -134,7 +131,8 @@ export default {
|
||||
itemManufacturer: '',
|
||||
hasTransferType: true // 待贴标签只显示有调拨类型的钢卷
|
||||
},
|
||||
total: 0
|
||||
total: 0,
|
||||
loadMoreTimer: null // 加载更多防抖定时器
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@@ -146,13 +144,11 @@ export default {
|
||||
},
|
||||
onReady() {
|
||||
// 页面就绪后再次计算高度(确保布局完成)
|
||||
this.$nextTick(() => {
|
||||
this.calcScrollViewHeight()
|
||||
})
|
||||
this.calcScrollViewHeight()
|
||||
},
|
||||
computed: {
|
||||
loadMoreStatus() {
|
||||
if (this.loading || this.loadMoreCooldown) return 'loading'
|
||||
if (this.loading) return 'loading'
|
||||
if (this.list.length >= this.total) return 'noMore'
|
||||
return 'more'
|
||||
}
|
||||
@@ -170,13 +166,11 @@ export default {
|
||||
// 各区域高度(单位:px)
|
||||
const navBarHeight = 44 // 导航栏高度
|
||||
const tabBarHeight = 50 // Tab栏高度
|
||||
const filterBarHeight = 60 // 筛选栏高度(留有余量)
|
||||
const filterBarHeight = 50 // 筛选栏高度(收起状态)
|
||||
const bottomSafeArea = systemInfo.safeAreaInsets?.bottom || 0 // 底部安全区域
|
||||
const tabBarOffset = 50 // 底部TabBar高度
|
||||
|
||||
// 计算 scroll-view 可用高度(确保最小高度为200px)
|
||||
let calcHeight = windowHeight - statusBarHeight - navBarHeight - tabBarHeight - filterBarHeight - bottomSafeArea - tabBarOffset
|
||||
this.scrollViewHeight = Math.max(calcHeight, 200)
|
||||
// 计算 scroll-view 可用高度
|
||||
this.scrollViewHeight = windowHeight - statusBarHeight - navBarHeight - tabBarHeight - filterBarHeight - bottomSafeArea
|
||||
|
||||
console.log('scroll-view 高度计算:', {
|
||||
windowHeight,
|
||||
@@ -185,8 +179,6 @@ export default {
|
||||
tabBarHeight,
|
||||
filterBarHeight,
|
||||
bottomSafeArea,
|
||||
tabBarOffset,
|
||||
calcHeight,
|
||||
scrollViewHeight: this.scrollViewHeight
|
||||
})
|
||||
},
|
||||
@@ -262,11 +254,6 @@ export default {
|
||||
} finally {
|
||||
this.loading = false
|
||||
this.refreshing = false
|
||||
// 延迟解除冷却期,防止立即再次触发加载
|
||||
setTimeout(() => {
|
||||
this.loadMoreCooldown = false
|
||||
console.log('加载冷却期结束')
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -303,97 +290,47 @@ export default {
|
||||
this.fetchList()
|
||||
},
|
||||
|
||||
// 滚动事件处理
|
||||
onScroll(e) {
|
||||
const scrollTop = e.detail.scrollTop
|
||||
const scrollHeight = e.detail.scrollHeight
|
||||
const clientHeight = this.scrollViewHeight
|
||||
|
||||
// 防止无效值
|
||||
if (!scrollHeight || !clientHeight) return
|
||||
|
||||
// 判断是否滑动到底部(距离底部小于 150px)
|
||||
const distanceToBottom = scrollHeight - scrollTop - clientHeight
|
||||
const isNearBottom = distanceToBottom < 150
|
||||
|
||||
// 判断滑动方向(增加最小变化阈值,防止微小抖动)
|
||||
const scrollDelta = scrollTop - this.lastScrollTop
|
||||
const isScrollingDown = scrollDelta > 3
|
||||
const isScrollingUp = scrollDelta < -3
|
||||
|
||||
console.log('滚动事件:', {
|
||||
scrollTop,
|
||||
scrollHeight,
|
||||
clientHeight,
|
||||
distanceToBottom,
|
||||
isNearBottom,
|
||||
isScrollingDown,
|
||||
isScrollingUp,
|
||||
isAtBottom: this.isAtBottom,
|
||||
canLoadMore: this.canLoadMore
|
||||
})
|
||||
|
||||
// 如果滑动到底部,标记状态但不加载
|
||||
if (isNearBottom && !this.isAtBottom) {
|
||||
console.log('滑动到底部,等待再次向上滑动触发加载')
|
||||
this.isAtBottom = true
|
||||
this.canLoadMore = true
|
||||
}
|
||||
|
||||
// 如果已经到底部,并且用户开始向上滑动,触发加载
|
||||
if (this.isAtBottom && this.canLoadMore && isScrollingUp) {
|
||||
console.log('底部后向上滑动,触发加载更多')
|
||||
this.canLoadMore = false
|
||||
this.doLoadMore()
|
||||
}
|
||||
|
||||
// 如果离开底部区域,重置状态
|
||||
if (!isNearBottom && this.isAtBottom) {
|
||||
console.log('离开底部区域')
|
||||
this.isAtBottom = false
|
||||
this.canLoadMore = false
|
||||
}
|
||||
|
||||
// 只有滑动方向明确时才更新 lastScrollTop
|
||||
if (Math.abs(scrollDelta) > 3) {
|
||||
this.lastScrollTop = scrollTop
|
||||
}
|
||||
},
|
||||
|
||||
// 实际执行加载更多
|
||||
doLoadMore() {
|
||||
console.log('执行加载更多', {
|
||||
// 加载更多
|
||||
onLoadMore() {
|
||||
console.log('触发加载更多', {
|
||||
listLength: this.list.length,
|
||||
total: this.total,
|
||||
loading: this.loading,
|
||||
loadMoreCooldown: this.loadMoreCooldown,
|
||||
pageNum: this.query.pageNum
|
||||
})
|
||||
|
||||
// 防抖保护:如果正在加载、冷却期或已到最后一页,直接返回
|
||||
if (this.list.length >= this.total || this.loading || this.loadMoreCooldown) {
|
||||
console.log('加载更多被阻止:已到最后一页、正在加载中或冷却期内')
|
||||
// 检查是否已加载全部数据
|
||||
if (this.list.length >= this.total) {
|
||||
console.log('加载更多被阻止:已加载全部数据')
|
||||
uni.showToast({
|
||||
title: '已加载全部数据',
|
||||
icon: 'none',
|
||||
duration: 1500
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 设置冷却期,防止连续触发
|
||||
this.loadMoreCooldown = true
|
||||
|
||||
// 增加短暂延迟,防止 scrolltolower 立即重复触发
|
||||
if (this._loadMoreTimer) {
|
||||
clearTimeout(this._loadMoreTimer)
|
||||
// 检查是否正在加载中
|
||||
if (this.loading) {
|
||||
console.log('加载更多被阻止:正在加载中')
|
||||
return
|
||||
}
|
||||
|
||||
this._loadMoreTimer = setTimeout(() => {
|
||||
this.query.pageNum++
|
||||
console.log('加载第', this.query.pageNum, '页')
|
||||
this.fetchList(true)
|
||||
}, 150)
|
||||
},
|
||||
// 防抖保护:防止重复点击
|
||||
if (this.loadMoreTimer) {
|
||||
console.log('加载更多被阻止:防抖保护中')
|
||||
return
|
||||
}
|
||||
|
||||
// 加载更多(点击按钮时调用)
|
||||
onLoadMore() {
|
||||
this.doLoadMore()
|
||||
// 设置防抖定时器
|
||||
this.loadMoreTimer = setTimeout(() => {
|
||||
this.loadMoreTimer = null
|
||||
}, 800)
|
||||
|
||||
// 执行加载
|
||||
this.query.pageNum++
|
||||
console.log('加载第', this.query.pageNum, '页')
|
||||
this.fetchList(true)
|
||||
},
|
||||
|
||||
// 重贴标签
|
||||
@@ -534,11 +471,11 @@ export default {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
.coil-list {
|
||||
padding-bottom: 40rpx;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.load-more-wrapper {
|
||||
padding: 30rpx 0;
|
||||
padding: 16rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -546,30 +483,47 @@ export default {
|
||||
&:active {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-hint {
|
||||
padding: 30rpx 0 50rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.load-more-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 12rpx 32rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 8rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08);
|
||||
|
||||
.hint-text {
|
||||
font-size: 28rpx;
|
||||
color: #1a73e8;
|
||||
font-weight: 500;
|
||||
animation: pulse 1.5s ease-in-out infinite;
|
||||
.btn-text {
|
||||
font-size: 26rpx;
|
||||
color: #1a73e8;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.btn-hint {
|
||||
font-size: 20rpx;
|
||||
color: #999999;
|
||||
margin-top: 4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% {
|
||||
opacity: 0.5;
|
||||
transform: translateY(0);
|
||||
.load-more-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12rpx 32rpx;
|
||||
|
||||
.loading-text {
|
||||
font-size: 26rpx;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: translateY(-3rpx);
|
||||
|
||||
&.no-more {
|
||||
padding: 16rpx 0;
|
||||
|
||||
.no-more-text {
|
||||
font-size: 22rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user