vue3+vant 移动端列表渲染

22 阅读1分钟

vue3+vant 移动端列表渲染

<template>
  <div>
    <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
      <van-list v-model:loading="loading" :finished="finished" @load="onLoad">
        <template v-for="(item, index) in list" :key="item.id">
          <slot :item="item" :index="item.id" :list="list" :idx="index"></slot>
        </template>
        <template #finished>
          <no-data
            :title="list.length ? '没有更多了~' : '暂无内容'"
            :showImg="!list.length"
          ></no-data>
        </template>
      </van-list>
    </van-pull-refresh>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import noData from '@/components/NoData.vue';

const props = defineProps({
  isPage: {
    type: Boolean,
    default: true
  },
  getListData: {
    type: Function,
    default: () => {}
  },
  otherParams: {
    type: Object,
    default: () => {}
  },
  pageSize: {
    type: Number,
    default: 20
  },
  isIndex: {
    type: Boolean,
    default: false
  }
});

const refreshing = ref(false);
const list = ref([]);
const loading = ref(false);
const finished = ref(false);
const pageNum = ref(1);
const currentPage = ref(0);

const handlePromiseData = promiseData => {
  return promiseData
    .then(res => {
      if (!props.isPage) {
        list.value = res.data;
        finished.value = true;
        refreshing.value = false;
        return res;
      } else {
        const { total, records } = res.data;
        if (refreshing.value) refreshing.value = false;
        list.value = [...list.value, ...records];
        if (
          total <=
          (props.isIndex ? res.data.size : pageNum.value * props.pageSize)
        ) {
          finished.value = true;
        } else {
          pageNum.value++;
        }
        return res;
      }
    })
    .catch(() => {
      loading.value = false;
      finished.value = true;
    });
};

const onLoad = async () => {
  if (currentPage.value === pageNum.value) return;
  currentPage.value = pageNum.value;
  loading.value = true;
  const promiseData = props.getListData({
    pageSize: props.pageSize,
    pageNumber: pageNum.value,
    ...props.otherParams
  });
  await handlePromiseData(promiseData);
  loading.value = false;
};

const onRefresh = () => {
  currentPage.value = 0;
  list.value = [];
  finished.value = false;
  pageNum.value = 1;
  setTimeout(() => onLoad(), 100);
};

defineExpose({ onRefresh, otherParams: props.otherParams });
</script>