vant组件二次封装-下拉刷新列表组件

一,二次封装的组件代码

<template>
  <van-pull-refresh
    v-model="refreshing"
    @refresh="onRefresh"
    success-text="已为您刷新成功"
  >
    <van-list
      v-model:loading="myLoading"
      :finished="finished"
      finished-text="没有更多了"
      @load="onLoad"
    >
      <div class="item-list" v-for="item in list" :key="item">
        <slot :item="item"></slot>
      </div>
      <img
        src="@/assets/img/empty.png"
        alt=""
        class="empty-image"
        v-if="list.length === 0"
      />
    </van-list>
  </van-pull-refresh>
</template>
<script setup>
import { ref, computed } from 'vue';
let emits = defineEmits([
  'update:loading',
  'update:finished',
  'update:pageCurrent',
  'update:pageSize',
  'getList'
]);
let props = defineProps({
  loading: {
    type: Boolean,
    require: true,
    default: false
  },
  finished: {
    type: Boolean,
    require: true,
    default: false
  },
  list: {
    type: Array,
    require: true,
    default: () => []
  },
  pageCurrent: {
    type: Number,
    require: true,
    default: 1
  },
  pageSize: {
    type: Number,
    require: true,
    default: 10
  }
});
const refreshing = ref(false);
let timeout;
const myLoading = computed({
  get: () => props.loading,
  set: val => {
    emits('update:loading', val);
  }
});
//加载
const onLoad = () => {
  if (refreshing.value) {
    refreshing.value = false;
    emits('update:finished', false);
    emits('update:loading', true);
    emits('update:pageCurrent', 1);
  }
  emits('getList');
};
//防抖处理,1s内只能下拉刷新一次
const onRefresh = () => {
  if (timeout) {
    clearTimeout(timeout);
  }
  timeout = setTimeout(onLoad, 1000);
};
</script>
<style lang="scss" scoped>
.van-pull-refresh {
  min-height: calc(100vh - 90px);
  :deep().van-pull-refresh__track {
    min-height: calc(100vh - 90px);
  }
  :deep() .van-pull-refresh__head {
    color: #8d8c8c;
  }
  :deep() .van-loading__text {
    color: #8d8c8c;
  }
  :deep() .van-loading__circular,
  .van-loading__text {
    color: #8d8c8c;
  }
}
.empty-image {
  margin-top: 50px;
  width: 50%;
}
</style>

二,父组件的使用

<template>
  <div class="order-box">
    <VantRefresh
      v-model:pageCurrent="pageCurrent"
      v-model:pageSize="pageSize"
      v-model:loading="loading"
      v-model:finished="finished"
      :list="list"
      @getList="getList"
    >
      <template #default="slotProps">
        <OrderListItem :item="slotProps.item"></OrderListItem>
      </template>
    </VantRefresh>
  </div>
</template>
<script setup>
import OrderListItem from './componcents/OrderListItem.vue';
import VantRefresh from '@/componcents/vant-refresh/VantRefresh.vue';
import { ref, onActivated } from 'vue';
import { httpPost } from '@/vue-use/useHttp.js';
const pageCurrent = ref(1); //当前页
const pageSize = ref(10); //每页个数
const list = ref([]); //数据列表
const loading = ref(false); //开启加载
const finished = ref(false); //已经到底了
//获取列表数据
async function getList() {
  let params = {
    TXCODE: 'STN011',
    pageCurrent: pageCurrent.value,
    pageSize: pageSize.value
  };
  const res = await httpPost(params);
  const orderList = res.data.orderList;
  if (pageCurrent.value === 1) {
    list.value = orderList;
  } else {
    list.value = list.value.concat(orderList);
  }
  console.log('我的订单列表', list.value);
  loading.value = false;
  pageCurrent.value++;
  if (res.data.orderList.length < pageSize.value) {
    finished.value = true;
  }
}
</script>
<style lang="scss" scoped>
.order-box {
  height: calc(100vh - 90px);
  padding-bottom: 180px;
  box-sizing: border-box;
  overflow: scroll;
}
</style>

三,解析

主要是用到这三个知识点

1,v-model:bindName

属性绑定,然后子组件props接收后,要要修改父组件的值,只需要emits(‘update:finished’, newValue)即可。无需再父组件中再调用函数。
vant组件二次封装-下拉刷新列表组件_第1张图片

2,computed的set函数

为了避免子组件自动变更props的值,通过computed进行一次转化,利用set函数变更父组件中的值。
vant组件二次封装-下拉刷新列表组件_第2张图片

3,作用域插槽

这里是父组件把list传给子组件使用,子组件又把list的item绑定到插槽上,提供给父组件使用。
vant组件二次封装-下拉刷新列表组件_第3张图片

你可能感兴趣的:(#,组件封装,vue.js)