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

89 篇文章 7 订阅
35 篇文章 1 订阅

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

需求很简单。我这边引入了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方法。手动调用。

  • 6
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
好的,针对您的问题,下面是vant-list实现下拉刷新和上拉加载的方法: 1. 安装vant 首先需要在项目中安装vant,可以通过npm或yarn进行安装: npm install vant --save 或者 yarn add vant 2. 引入vant 在需要使用vant的页面中引入vant: import Vue from 'vue'; import Vant from 'vant'; import 'vant/lib/index.css'; Vue.use(Vant); 3. 使用vant-list 在页面中使用vant-list组件,用于展示列表数据: <van-list :finished="finished" @load="onLoad" @refresh="onRefresh"> <!-- 列表项 --> </van-list> 其中,@load和@refresh分别是上拉加载下拉刷新的事件,finished用于控制是否已加载完所有数据。 4. 实现下拉刷新 在页面的methods中定义onRefresh方法,用于处理下拉刷新事件: export default { data() { return { list: [], // 列表数据 page: 1, // 当前页码 pageSize: 10, // 每页数据数量 finished: false // 是否已加载完所有数据 }; }, methods: { async onRefresh() { this.page = 1; // 下拉刷新时重置页码 this.list = []; // 清空列表数据 await this.loadData(); // 加载数据 this.finished = false; // 重置finished状态 }, async loadData() { // 根据当前页码和每页数据数量加载数据 const data = await api.getList(this.page, this.pageSize); if (data.length > 0) { this.list = this.list.concat(data); // 将数据添加到列表中 this.page++; // 页码+1 } else { this.finished = true; // 已加载完所有数据 } } } }; 5. 实现上拉加载 在页面的methods中定义onLoad方法,用于处理上拉加载事件: export default { data() { return { list: [], // 列表数据 page: 1, // 当前页码 pageSize: 10, // 每页数据数量 finished: false // 是否已加载完所有数据 }; }, methods: { async onRefresh() { this.page = 1; // 下拉刷新时重置页码 this.list = []; // 清空列表数据 await this.loadData(); // 加载数据 this.finished = false; // 重置finished状态 }, async onLoad() { if (this.finished) return; // 如果已加载完所有数据则直接返回 await this.loadData(); // 加载数据 }, async loadData() { // 根据当前页码和每页数据数量加载数据 const data = await api.getList(this.page, this.pageSize); if (data.length > 0) { this.list = this.list.concat(data); // 将数据添加到列表中 this.page++; // 页码+1 } else { this.finished = true; // 已加载完所有数据 } } } }; 通过以上步骤,就可以实现vant-list下拉刷新和上拉加载功能了。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值