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

需求很简单。我这边引入了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>

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

时间紧,目前就这样了。

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

单纯只想使用onLoad方法

data() {
      return {
        offset:0,//滚动条与底部距离小于 offset 时触发load事件,默认300
        pageNo: 1, // 当前页码
        pageSize: 10, // 分页大小
        total: 0, // 查询总条数
        loading: false, // 滚动加载中
        finished: false, // 滚动加载完成
        list:[ ],
      };
    },

<van-list
      v-model="loading"
      :finished="finished"
      :offset="offset"
      :immediate-check="false"
      finished-text="没有更多了"
      @load="onLoad"
    >
    	<p  v-for="(item, index) in list" :key="index>{{item.name}}</p>
</vant-list>


getDutyList() {
        return new Promise((resolve, reject) => {
          let params = {
            pageNo: this.pageNo,
            pageSize: this.pageSize,
          };
          this.axios.get(params).then((res) => {
            if (res.data.status == 0) {
                  if (res.data.data.resultData.length > 0) {
                    let result = {
                      total: res.data.data.total,
                      pageNo: res.data.data.pageNo,
                      data: res.data.data.resultData,
                    };
                    resolve(result);
              }
            }
          }).catch((err) => {
            reject(err);
          });
        })
      },

      // 滚动加载更多
      onLoad() {
        this.loading = true;
        this.getDutyList().then((res) => {
          this.list= this.list.concat(res.data);
          if (this.list.length>=res.total) {
            this.finished = true;
          } else {
            this.finished = false;
            this.pageNo += 1
          }
          this.loading = false
        });
      },

注意: :immediate-check="false" 设置关闭后,就需要自己手动触发第一次onLoad方法。手动调用。

Logo

前往低代码交流专区

更多推荐