vue移动端实现滚动加载更多和下拉刷新功能,vant-ui的PullRefresh和List组件结合使用的坑

需求,移动端列表页不再是分页实现点击上一页下一页,需要实现滚动到底部自动加载下一页,页面整个下拉的话,就刷新当前页面的数据。

需求很简单。我这边引入了vant-ui,实现起来呢,遇到各种问题。网上找了一大圈,发现一个能打的都没有,都有问题。我整个人都不好了。为什么呢?

特此先记录一下,我的实现过程。虽然,不是最好的实现方式,但是,目前各种暴力测试,没有发现bug了。总算能用了。

测试遇到的问题有哪些呢?下拉刷新,数据突然没有了,页面list空白;加载到第二页,还在加载中,又暴力的进行下拉刷新,导致这个第二页的数据,跑到第一页的数据顶部,再后面又是第二页数据,第三页数据;不说了,测试了很多方法,都不行。这个破玩意,把我折腾的,实在是不轻。

目前的方法,比较稳定了,至少没有这些莫名其妙的bug了。

    <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
      <van-list
        v-model="loading"
        :finished="finished"
        finished-text="没有更多了"
        @load="onLoad"
      >
        <div
          v-for="(item, index) in list"
          :key="index"
          class="item-wrap van-hairline--bottom"
        >
          <div class="item-name">{{ item.name }}</div>
        </div>
      </van-list>
    </van-pull-refresh>

。。。。。。。。。。
data() {
    return {
      list: [], // 列表数据
      pageIndex: 1, // 当前页码
      pageSize: 10, // 分页大小
      total: 0, // 查询总条数
      loading: false, // 滚动加载中
      finished: false, // 滚动加载完成
      isLoading: false, // 下拉强制刷新
    };
  },

list组件,监听的方法是onLoad, 由loading和finished两个来控制。
PullRefresh组件,由isLoading来控制,监听的方法是onRefresh

分离出获取数据ajax的函数,fetchList

// 获取数据列表
    fetchList() {
      return new Promise((resolve, reject) => {
        let para = {
          data: {
            confirm: false,
            pageIndex: this.pageIndex,
            pageSize: this.pageSize,
          },
        };
        temperatureWarningList(para)
          .then((res) => {
            let result = {
              total: res.data.recordTotal,
              pageIndex: res.data.pageIndex,
              list: res.data.list,
            };
            resolve(result);
          })
          .catch((err) => {
            reject(err);
          });
      });
    },

onLoad的内容

 // 滚动加载更多
    onLoad() {
      this.loading = true;
      this.fetchList().then((res) => {
        if (res.list.length < this.pageSize) {
          // 数据小于10条,已全部加载完毕finished设置为true
          this.finished = true;
        }
        if (res.list.length === 0) {
          // 数据返回为空,表示没有数据了
          this.loading = false;
          this.finished = true;
        }
        // fix第二页数据未加载完成就强制下拉刷新,导致上一次的第二页的数据跑到这一次第一页的数据的前面的bug
        if (this.pageIndex == res.pageIndex) {
          this.pageIndex = res.pageIndex + 1;
          this.list = this.list.concat(res.list);
        }
        this.loading = false;
      });
    },

onRefresh的内容

// 下拉刷新
    onRefresh() {
      this.list = [];
      this.pageIndex = 1;
      this.finished = false;
      this.loading = true;
      this.onLoad();
      this.isLoading = false; // 下拉加载完成,关闭,不然就会有两个显示加载中的转圈圈。list本身就有一个了。啊。好恶心。
    },

如果拉动的内容,不是全屏,就需要改写 van-pull-refresh的样式,用命名空间覆盖或是重写。我的这里是由于自己的样式在vant的样式后面引入,加入scoped也可以生效。如果不能生效,写一个不带scoped的style,然后外面套一层class类名作为命名空间。

<style lang="less" scoped>
.van-pull-refresh {
  min-height: calc(100vh - 46px);
}
</style>

如果您有更好的方法,还希望不吝赐教,请收下我的膝盖。

时间紧,目前就这样了。

未来,有更好的解决办法了,再来更新。记录一下。

你可能感兴趣的:(移动端,前端技术积累,vue)