uni-app解决scroll-view下拉刷新无法正常恢复的问题
uni-app解决scroll-view下拉刷新无法正常恢复的问题
关于scroll-view组件的下拉刷新,无论是uni-app还是微信小程序,官方都说得不是很明白,有一个非常关键的关键规则没说清楚,组件属性例子:
refresher-triggered="triggered" @refresherrefresh="onRefresh" @refresherrestore="onRestore" scrolltolower="loadMore"
- 通过程序将triggered设为true时,将触发onRefresh;
- 不管triggered为何值,在界面中下拉,也会触发onRefresh,但不会自动改变triggered值(不能双向绑定,这是问题的根本原因);
- onRefresh执行完毕,不会自动触发onRestore(这是问题的表现),使得刷新图标一直显示,必须是triggered由true变为false,才会触发onRestore并隐藏刷新图标;如果triggered一直为false,或一直为true,都不会触发。
解决办法:
- 在进入onRefresh后,如果triggered为false,则将它置为true,当执行完你的刷新操作(通常是获取新的数据)后,将triggered置为false。
- 由于上一步中将triggered置为true,会再次触发onRefresh,故需再增加一个_freshing,表示是否正在执行刷新操作,在onRefresh中做判断,如_freshing为true,不执行刷新操作直接返回。
如果scroll-view有多个,要每个用自己的 triggered和refreshing来控制。
代码如下,和官方差不多,注意有关键的几个细节不同。
<script>
export default {
data() {
return {
triggered: false,
_freshing: false
}
},
onLoad() {
this._freshing = false;
setTimeout(() => {
this.triggered = true; // 触发onRefresh来加载自己的数据,如果不用这种方式,不要在此改变triggered的值
}, 1000)
},
methods: {
onPulling(e) {
console.log("onpulling", e);
},
onRefresh() {
if (this._freshing) return;
this._freshing = true;
if (!this.triggered) // 界面下拉触发,triggered可能不是true,要设为true
this.triggered = true;
setTimeout(() => {
this.triggered = false; // 触发onRestore,并关闭刷新图标
this._freshing = false;
}, 3000)
},
onRestore() {
console.log("onRestore");
},
onAbort() {
console.log("onAbort");
}
}
}
</script>
1 回复
在uni-app中,scroll-view
组件的下拉刷新功能(enableBackToTop
和scroll-y
属性配合@scrolltolower
事件)确实可能会遇到无法正常恢复的问题。这通常是由于事件处理不当或状态管理问题导致的。以下是一个简化的代码示例,展示了如何实现一个可靠的下拉刷新功能,并确保刷新状态能够正确恢复。
代码示例
1. 页面模板 (template)
<template>
<view>
<scroll-view
scroll-y="true"
:enable-back-to-top="true"
@scrolltolower="handleScrollToLower"
ref="scrollView"
>
<view v-for="item in items" :key="item.id">{{ item.name }}</view>
<!-- 模拟长列表 -->
<view v-for="i in 100" :key="i">更多内容...</view>
</scroll-view>
<button @click="restoreScrollPosition">恢复滚动位置</button>
</view>
</template>
2. 脚本部分 (script)
<script>
export default {
data() {
return {
items: Array.from({ length: 20 }, (_, i) => ({ id: i, name: `Item ${i + 1}` })),
isRefreshing: false,
savedScrollTop: 0,
};
},
methods: {
handleScrollToLower() {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.$refs.scrollView.scrollTop = 0; // 立即重置到顶部
// 模拟异步数据加载
setTimeout(() => {
this.loadMoreData();
this.isRefreshing = false;
}, 2000);
}
},
loadMoreData() {
// 假设我们加载了更多数据
for (let i = this.items.length; i < this.items.length + 10; i++) {
this.items.push({ id: i, name: `New Item ${i + 1}` });
}
// 恢复之前的滚动位置(这里简单处理为0,实际应用中需保存scrollTop)
// this.$refs.scrollView.scrollTop = this.savedScrollTop;
},
restoreScrollPosition() {
// 在需要时手动恢复滚动位置(例如从其他页面返回)
// this.$refs.scrollView.scrollTop = this.savedScrollTop;
},
},
};
</script>
注意事项
- 在实际应用中,
savedScrollTop
应该在用户开始下拉刷新之前保存当前的滚动位置。 - 在
loadMoreData
方法中,加载完新数据后,如果需要恢复滚动位置,应该使用之前保存的scrollTop
值。 - 由于uni-app的跨平台特性,不同平台(如小程序、H5、App)可能对
scroll-view
的实现有细微差异,测试时需确保在所有目标平台上表现一致。
通过上述代码示例,你可以实现一个基本的下拉刷新功能,并确保刷新后能正确恢复滚动状态。