vue基于vant封装上拉加载/下拉刷新组件ListScroller

1,054 阅读1分钟

效果

动图.gif

一、ListScroller组件封装 components/public/ListScroller/index.vue

<template>
  <van-pull-refresh class="list-scroller" v-model="refreshing" @refresh="onRefresh" :style="{height: listHeight}">
    <van-list v-model="loading" @load="onLoad" offset='300'>
      <slot></slot>
    </van-list>
  </van-pull-refresh>
</template>
<script>
export default {
  name: 'ListScroller',
  props: { height: { type: String | Number, default: '' } },
  watch: {
    height: {
      handler(val) {
        this.setListHeight(Math.abs(val))
      },
      immediate: true
    }
  },
  data() {
    return {
      loading: false, // 加载更多
      refreshing: false, // 重新加载
      listHeight: '' // 容器高度  可传 66 -66 '66' '-66' 全屏高度则不传
    }
  },
  methods: {
    setListHeight(height) {
      const h = height
        ? document.documentElement.clientHeight - height + 'px'
        : '100%'
      this.listHeight = h
    },
    onRefresh() {
      this.$emit('on-pulldown-loading', () => (this.refreshing = false)) // 下拉刷新成功后关闭顶部刷新状态
    },
    onLoad() {
      this.$emit('on-pullup-loading', () => (this.loading = false)) // 上拉加载成功后关闭底部加载状态
    }
  }
}
</script>
<style lang="less" scoped>
.van-pull-refresh.list-scroller {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
</style>

二、使用

<template>
  <div class="list">
    <header>头部</header>
    <ListScroller height='-50' @on-pulldown-loading="refrash" @on-pullup-loading="loadMore">
      <ul class="scroller-container" v-if="list.length > 0">
        <li v-for="(item,index) of list" :key="index">
          <p>{{item.projectName}}</p>
          <p>{{item.addTime}}</p>
        </li>
      </ul>
      <div v-else class="empty">暂无数据~</div>
    </ListScroller>
  </div>
</template>
<script>
import ListScroller from '@/components/public/ListScroller'
import { listApi } from '@/api/request'
export default {
  data() {
    return {
      queryParams: { page: 1, pageSize: 10 },
      totalRecords: '',
      list: []
    }
  },
  created() {
    this.getList()
  },
  methods: {
    async getList() {
      const { queryParams } = this
      const params = { ...queryParams, flowTrackType: 2 }
      const { success, data, totalRecords } = await listApi(params)
      if (success) {
        this.totalRecords = totalRecords
        if (queryParams.page === 1) {
          this.list = data
        } else {
          this.list.push(...data)
        }
      }
    },
    // 刷新
    async refrash(cb) {
      this.queryParams.page = 1
      await this.getList()
      cb && cb()
    },
    // 加载更多
    async loadMore(cb) {
      const { list, totalRecords } = this
      if (totalRecords > list.length) {
        this.queryParams.page++
        await this.getList()
        cb && cb()
      } else {
        cb && cb()
      }
    }
  },
  components: { ListScroller }
}
</script>
<style lang="less" scoped>
.list {
  height: 100%;
  background-color: rgba(255, 0, 0, 0.1);
  font-size: 14px;
  > header {
    background-color: rgba(0, 0, 255, 0.1);
    line-height: 50px;
    text-align: center;
  }
  ul.scroller-container {
    padding: 10px;
    > li {
      height: 80px;
      background-color: #fff;
      margin-top: 10px;
      border-radius: 10px;
      padding: 10px;
      &:first-of-type {
        margin-top: 0;
      }
      > p {
        line-height: 20px;
      }
    }
  }
  .empty {
    padding: 100px;
    text-align: center;
  }
}
</style>