Bootstrap

前端h5上拉加载下拉刷新分页vant


<template>
  <div class="cart">
    <div v-if="!loading">
      <van-pull-refresh
        v-model="isRefresh"
        @refresh="refreshClick"
        loading-text="正在请求数据"
        success-text="数据刷新成功"
      >
        <van-list
          v-model:loading="isListLoading"
          :finished="isFinished"
          :offset="state.offset"
          :immediate-check="false"
          @load="onLoad"
        >
          <div class="cart-item" v-for="(item, n) in datas" :key="n">
            <van-checkbox
              v-model="checked"
              icon-size="21px"
              class="check-box"
              checked-color="#D6AB6B"
            ></van-checkbox>
            <van-card
              :num="item.cartNum"
              :title="item.storeName"
              :thumb="item.image"
            >
              <template #price>
                <div class="price">
                  <van-image
                    width="14px"
                    height="14px"
                    style="margin-right: 7px"
                    :src="ico"
                  />
                  <span>{{ item.price }}</span>
                </div>
              </template>
              <template #num>
                <van-stepper v-model="item.cartNum" />
              </template>
            </van-card>
          </div>
        </van-list>
      </van-pull-refresh>
    </div>
    <div
      v-else
      style="
        background: rgb(255, 255, 255);
        height: 100vh;
        display: grid;
        place-items: center;
      "
    >
      <van-loading size="24px" color="#E0C198" vertical>加载中...</van-loading>
    </div>

    <van-empty
      class="empty-box"
      v-if="false"
      :image="cartEmtyIco"
      description="您的购物车还没有商品"
    />

    <van-submit-bar
      :placeholder="true"
      :price="3050"
      :label="'已选' + 3 + '件' + ',合计:'"
      button-text="结算"
      currency=""
      @submit="onSubmit"
      suffix-label="当前积分:222"
      :disabled="!isData ? false : true"
    >
      <van-checkbox
        v-model="checked"
        checked-color="#D6AB6B"
        icon-size="21px"
      ></van-checkbox>

      <span class="word-style"> 全选 </span>
    </van-submit-bar>
  </div>
</template>
<script setup lang="ts">
import { onBeforeMount, ref, reactive, watch } from 'vue'
import cartEmtyIco from '../../assets/images/cart-emty-ico.png'
import { getCartList } from '../../request/api'
import ico from '../../assets/images/ico.png'
const pageModel = reactive({
  page: 1,
  limit: 10,
  total: 0,
  pages: 0,
})
const state = {
  offset: 6, // 滚动条与底部距离小于 offset 时触发load事件
  nodata: false,
}

const isRefresh = ref(false)
const isFinished = ref(false)
const isListLoading = ref(false)
const loading = ref(false)
const checked = ref(false)
onBeforeMount(() => {
  loading.value = true
  getList()
})

// 下拉刷新列表
const refreshClick = () => {
  isRefresh.value = true
  isFinished.value = false
  isListLoading.value = true
  pageModel.page = 1
  getList()
}

//上拉加载下一页
const onLoad = () => {
  isListLoading.value = true
  if (pageModel.page + 1 > pageModel.pages) {
    isFinished.value = true
    isListLoading.value = false
    return
  } else {
    pageModel.page = pageModel.page + 1
    getList()
  }
}

const params = ref({
  page: 1,
  limit: 10,
  type: 'sum',
  numType: true,
  isValid: true,
})
const datas: any = ref([])
// 初始化数据
const getList = () => {
  params.value.page = pageModel.page
  params.value.limit = pageModel.limit
  getCartList(params.value).then((res: any) => {
    let arr = res.data.list
    pageModel.pages = res.data.totalPage
    pageModel.total = res.data.total
    isListLoading.value = false

    isRefresh.value = false
    if (pageModel.page === 1) {
      datas.value = arr
    } else {
      datas.value = [...datas.value, ...arr]
    }
    loading.value = false
  })
}

watch(
  () => pageModel.total,
  (newValue, oldValue) => {
    console.log('watch', newValue > 0, oldValue)
    state.nodata = !(newValue > 0)
  }
)
</script>
<style scoped lang="less">
.cart {
  height: 100%;
  min-height: 100vh;
  background: white;
  padding: 12px 16px;
  :deep(.van-card) {
    background: white;
    width: 100%;
    padding: 5px;
    padding-bottom: 10px;
  }
  .cart-item {
    padding-left: 10px;
    background: white;
    display: flex;
    border-bottom: 1px solid #ebebed;
  }
  .check-box {
    padding-right: 5px;
  }
  .price {
    font-weight: bold;
    font-size: 18px;
  }
  :deep(.van-submit-bar__button) {
    width: 83px;
    background: linear-gradient(to right, #f3d6a4, #e0c198, #e0c198);
    font-size: 14px;
    color: #222222;
    font-weight: normal;
  }
  :deep(.van-button--disabled) {
    background: #ebebed;
    color: #a5a5ac;
    font-size: 14px;
    font-weight: normal;
    width: 83px;
  }
}
.word-style {
  font-size: 14px;
  margin-left: 13px;
  color: #222222;
}
:deep(.van-submit-bar__text) {
  font-size: 12px;
}
:deep(.van-submit-bar__suffix-label) {
  font-weight: normal;
  color: #d6ab6b;
  font-size: 12px;
}
:deep(.van-submit-bar__price) {
  color: #222222;
}
:deep(.van-submit-bar__bar) {
  padding: 8px;
  border-top: 1px solid #ebebed;
}
.empty-box {
  background: white;
  height: 100vh;
}
:deep(.van-empty__image) {
  width: 120px;
  height: 120px;
}
:deep(.van-stepper__minus) {
  background: white;
  color: #888888;
}
:deep(.van-stepper__plus) {
  width: 20px;
  height: 20px;
  background: white;
}
:deep(.van-card__title) {
  font-size: 14px;
}
</style>

;