天天看点

APP开发-Vue3+vant实现数据列表下拉分页功能

一、需求分析

1、数据列表页面初始化显示十条数据,当用户下拉页面的时候会再自动请求十条数据,如果数据加载完成,显示提示信息’已经到底了’

二、 分页效果图

从动图中我们可以看出页面在下拉的时候会自动触发数据请求,在右边的Network栏中,我们可以监测它是往后台发送请求的,而其currentPage代表的请求页数每次也会自动加一。
APP开发-Vue3+vant实现数据列表下拉分页功能
前台需要的数据格式,其中dataCount代表我们所查询出来的数据总量,逻辑判断分页就是要根据dataCount来判断。productList也就是我们分页查询出来的数据list
APP开发-Vue3+vant实现数据列表下拉分页功能

三、后台分页逻辑

当我们数据列表数据量大的时候,我们一般都会采用分页的展示。怎么样实现分页?首先,前台我们要告诉后台,我们需要请求第几页数据,并且把每页展示的数据量告诉我。

后台处理就比较简单了,因为是使用mysql的数据库,所以可以直接使用limit关键字进行分页。

SELECT * from table limit currentPage, pageSize
           

mysql分页比较简单,其中currentPage代表起始查询的下标, pageSize代表查询的数据量

SELECT * from table limit 10,  10
           

上个sql语句表示我要查询从下标10开始,往后的10条数据。

四、前台分页逻辑

缕清楚我们后台的分页逻辑,当我们前台请求接口的时候也会清楚该如何传递参数。前台使用vant组件,此组件也提供了分页的组件van-list,根据这个组件的介绍我们可以了解到List组件通过 loading 和 finished 两个变量控制加载状态,当组件滚动到底部时,会触发 load 事件并将 loading 设置成true。此时可以发起异步操作并更新数据,数据更新完毕后,将 loading 设置成 false 即可。若数据已全部加载完毕,则直接将finished 设置成 true 即可。

vant官网:https://vant-contrib.gitee.io/vant/v3/#/zh-CN/list

五、分页共通组件的提取

因为我们分页的机能在很多地方都要用到,所以首先我们要把van-list这个可以分页的组件提为共通组件,此共通组件的主要目的是:触发下拉请求数据操作,当后台数据请求完毕后则显示加载完成。此共通组件在初始化的时候会往父组件发射一个事件,父组件要接受这个事件并且实现页面初始化请求的API。API请求完成以后再次回调这个分页组件,让分页组件去进行判断数据是否请求完毕。

html代码:

<template>
  <div v-if="noData">
    <div>
      <van-list
        v-model:loading="loading"
        :finished="finished"
        @load="onLoad"
      >
        <!-- 加载显示 -->
        <template #loading>
          <img :src="require('@/assets/img/loading/u431.svg')" style="width:30px"/>
          <div>正在加载更多</div>
        </template>
        <!-- 到底显示 -->
        <template #finished v-if="isBottom">
          <div>已经到底了</div>
        </template>
      </van-list>
    </div>
  </div>
  <empty-bar v-else :content="descriptionLabel"/>
</template>
           

js代码:

export default {
  props: {
    isBottom: {
      type: Boolean,
      default: true,
    },
    descriptionLabel: { // 零件的条件下信息提示
      type: String,
      default: '',
    },
  },
  data() {
    return {
      loading: false,
      finished: false,
      scrollDataLength: 0,
      noData: true,
    };
  },
  methods: {
    // 同类推荐信息获取
    onLoad() {
      const that = this;
      setTimeout(() => {
        this.$emit('get-scroll-data-list', (length, count) => {
          if (count <= 0) {
            // 无数据展示
            that.noData = false;
            // 数据全部加载完成
            that.finished = true;
          } else {
            that.scrollDataLength += length;
            that.loading = false;
            if (that.scrollDataLength >= count) {
              // 数据全部加载完成
              that.finished = true;
            }
          }
        });
      }, 700);
    },
  },
};
           

六、列表共通组件的提取

我们需要展示的商品列表,资讯列表等,这些显示的排版内容、样式之类的都是一样的,只是内容是要动态获取,所以我们对这些都要提取共通组件,根据不同的需求显示不同的样式,这里不再赘述。

七、分页的实现

在html代码里面我们要引入分页组件scroll,还有就是我们写的分页列表组件,这个就是需求不同,内容不同了。分页组件里面,接受子组件发射的事件并绑定一个获取列表数据的事件,分页列表子组件就是我们获取到的数据list进行循环展示。

html代码:

<template>
  <div class="container">
	<!-- 分页组件 -->
    <scroll
      v-if="sProductListBarFlg"
      @get-scroll-data-list="getRecommendList"
      :descriptionLabel="recommendLabel"
      class="scroll"
    >
	  <!-- 分页列表组件 -->		
      <div>
        <article-bar
          v-for="(item, index) in recommendList"
          :key="index"
          :reCommendList="item"
        />
      </div>
    </scroll>
  </div>
</template>
           

js代码:

setup() {
    const { proxy } = getCurrentInstance();
    const state = reactive({
      recommendList: [], // 信息List
      recommendCurrentPage: 0, // 当前页
      dataCount: 10, // 显示数据数量
      recommendLabel: '暂无相关推荐,切换其他的看看吧~',
      sProductListBarFlg: true,
    });

    // 获取推荐列表
    const getRecommendList = (callback) => {
      // 获取推荐list
      proxy.$api.getRecommendList({
        currentPage: state.recommendCurrentPage, // 当前页
        dataCount: state.dataCount, // 显示数据数量
      }).then(({ data }) => {
        if (data.data.dataCount !== 0) {
          // 子组件回调函数
          callback(state.recommendList.length, data.data.dataCount);
          // 将请求到的数据list加入到信息List
          state.recommendList = state.recommendList.concat(data.data.recommendList);
          // 当前页
          state.recommendCurrentPage += 1;
        } else {
          // 推荐信息List
          state.recommendList = [];
          // 子组件回调函数
          callback(state.recommendList.length, 0);
        }
      });
    };

    return {
      ...toRefs(state),
      getRecommendList,
    };
  },
           

我们初始化调用后台的时候,会自动请求前十条数据和一共查询到的数据总量,当我们请求成功回调分页组件的时候,会把查询到的数据总量和当前api查询的数据总量发送给分页组件,在分页组件进行判断看查询到的数据总量和每次分页查询到的数据量总和进行比较。

逻辑代码如下:

if (count <= 0) {
            // 无数据展示
            that.noData = false;
            // 数据全部加载完成
            that.finished = true;
          } else {
            that.scrollDataLength += length;
            that.loading = false;
            if (that.scrollDataLength >= count) {
              // 数据全部加载完成
              that.finished = true;
            }
          }