uni-app解决scroll-view下拉刷新无法正常恢复的问题

发布于 1周前 作者 nodeper 来自 Uni-App

uni-app解决scroll-view下拉刷新无法正常恢复的问题
关于scroll-view组件的下拉刷新,无论是uni-app还是微信小程序,官方都说得不是很明白,有一个非常关键的关键规则没说清楚,组件属性例子:
refresher-triggered="triggered" @refresherrefresh="onRefresh" @refresherrestore="onRestore" scrolltolower="loadMore"

  1. 通过程序将triggered设为true时,将触发onRefresh;
  2. 不管triggered为何值,在界面中下拉,也会触发onRefresh,但不会自动改变triggered值(不能双向绑定,这是问题的根本原因);
  3. onRefresh执行完毕,不会自动触发onRestore(这是问题的表现),使得刷新图标一直显示,必须是triggered由true变为false,才会触发onRestore并隐藏刷新图标;如果triggered一直为false,或一直为true,都不会触发。

解决办法:

  1. 在进入onRefresh后,如果triggered为false,则将它置为true,当执行完你的刷新操作(通常是获取新的数据)后,将triggered置为false
  2. 由于上一步中将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组件的下拉刷新功能(enableBackToTopscroll-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的实现有细微差异,测试时需确保在所有目标平台上表现一致。

通过上述代码示例,你可以实现一个基本的下拉刷新功能,并确保刷新后能正确恢复滚动状态。

回到顶部