vue---vant实现下拉刷新上拉加载

2,406 阅读3分钟

运用vant实现下拉刷新上拉加载功能

功能:

前提:

引入了 vantUI库

代码:

<template>
  <div class="trainingCenter">
      <van-sticky>
        <van-search
          ref="getheight"
          v-model="this.parmas.name"
          shape="round"
          background="#4378BE"
          placeholder="请输入"
          show-action
          @search="onSearch"
          @clear="onCancel"
          @input="onInput"
          style="background:rgba(67,120,190,1);box-shadow:0px 2px 2px 0px rgba(0,0,0,0.3);"
        >
          <template #action>
            <div style="color:#fff;" @click="handleSearch">搜索</div>
          </template>
        </van-search>
      </van-sticky>

      <template >

        <div class="scroll_content"  v-if="pageLoading">
          <div class="recommended_today">
            <div class="rt_title">今日推荐</div>
            <van-swipe :loop="false" :show-indicators="false" :width="163" :height="145">
              <van-swipe-item
                v-for="(item,index) in todayData"
                :key="index"
                @click="handleSwipeClick(item)"
              >
                <div class="img_box rt_img_box">
                  <van-image class="rt_img" :src="item.url" alt fit="cover" />
                  <img class="img_open" src="../../../assets/images/train/video_open_icon.png" alt />
                </div>
                <div class="rt_des">{{item.des}}</div>
              </van-swipe-item>
            </van-swipe>
          </div>

          <div class="traininds_box">
              <van-tabs swipeable  sticky
                  title-inactive-color="#454545"
                  title-active-color="#0091FF"
                  line-width='26'
                  :offset-top="heightall"
                  @change="handleChangeTag"
              >
                <van-tab class="tb_van-tab" v-for="index in 4" :title="'标签 ' + index" :key="index" >

                  <van-pull-refresh
                    v-model="isDownLoading"
                    success-text="刷新成功"
                    @refresh="onRefresh"
                  >

                      <van-list v-model="isUpLoading"
                          :finished="upFinished"
                          finished-text="没有更多了"
                          @load="onLoadList"
                          :immediate-check="false"
                          :offset="100"
                      >

                          <van-grid class="traininds_content" :border="false" :column-num="3" :square="false">
                            <van-grid-item v-for="(item,index) in list" :key="index">
                                <div class='tc_item'>
                                  <div class="img_box tc_img_box">
                                      <van-image class="tc_img" :src="item.avatar" alt fit="cover" />
                                      <img class="img_open" src="../../../assets/images/train/video_open_icon.png" alt />
                                    </div>
                                  <div class="tc_des">{{item.name}}</div>
                                </div>
                            </van-grid-item>

                          </van-grid>

                      </van-list>
                    
                  </van-pull-refresh>
                  
                </van-tab>
              </van-tabs>
          </div>
        </div>

        <PageLoading v-else></PageLoading>

      </template>
    
        
  </div>
</template>

<script>
import { Search, List, Grid, GridItem, Sticky, Swipe, SwipeItem, Image, Tab, Tabs,PullRefresh ,Toast} from "vant";
import {getCustomerList} from '@/api/index';
import PageLoading from "@/components/PageLoading";

export default {
  name: "trainingCenter",
  //引用的组件
  components: {
    [Sticky.name]: Sticky,
    [Swipe.name]: Swipe,
    [SwipeItem.name]: SwipeItem,
    [Search.name]: Search,
    [List.name]: List,
    [Grid.name]: Grid,
    [GridItem.name]: GridItem,
    [Image.name]: Image,
    [Tab.name]: Tab,
    [Tabs.name]: Tabs,
    [PullRefresh.name]:PullRefresh,
    [Toast.name]:Toast,
    [List.name]:List,
    PageLoading
  },
  data() {
    return {
      heightall: 0,
      active: 0,
      todayData: Object.assign({}, todayData),
      trainData: Object.assign({}, trainData),
      list:[],
      pageLoading:false,
      isDownLoading: false, // 下拉刷新
      isUpLoading: false, // 上拉加载
      upFinished: false, // 上拉加载完毕
      pageInfo: {
        currentPage: 1,
        pageSize: 18,
        totalPage: 0,
        totalRecords: 0
      },
      parmas:{
        "currentPage":1,
        "pageSize":20,
      }

    };
  },
  created: function() {
    //dom加载完成前渲染,在实例创建完成后被立即调用
    this.parmas.pageSize = this.pageInfo.pageSize
    this.list=[];
    this.onLoad();
  },
  mounted() {
    //dom加载完成后渲染 获取offset-top的值
    this.$nextTick(function() {
      this.heightall = this.$refs.getheight.offsetHeight;
    });
  },
  methods: {
    onLoad() {
      this.parmas.currentPage = this.pageInfo.currentPage

      getCustomerList(this.parmas).then(res=>{
        if(res.code == 100){

           this.pageLoading = true

           // 加载状态结束
            this.isUpLoading = false;
         
           let data = res.data;
                     
           if (data == null || data.length === 0) {
              // 加载结束
              this.finished = true;
              return false;
          }

           //数据处理
          if(this.pageInfo.currentPage==1){
            this.list = data
          }else{
            // 将新数据与老数据进行合并
            this.list = this.list.concat(data);
          }
          this.pageInfo = res.pageInfo

          //如果列表数据条数>=总条数,不再触发滚动加载
          if (this.list.length >= this.pageInfo.totalRecords) {
            this.upFinished = true;
          }
          
        }
      }).finally(() => {
        this.isDownLoading = false
        this.isUpLoading = false
      })

    },
    // 上拉加载请求方法 加载更多
    onLoadList() {
      //滚动加载时触发,list组件定义的方法
      if(this.pageInfo.totalPage > this.pageInfo.currentPage && this.pageInfo.totalPage != this.pageInfo.currentPage ){
        this.pageInfo.currentPage++;
        this.onLoad();
      }
    },
    onRefresh() {
       this.pageInfo.currentPage = 1
       this.upFinished = false // 不写这句会导致你上拉到底过后在下拉刷新将不能触发下拉加载事件
       this.onLoad()
    },
    handleSwipeClick(item) {
      console.log(item);
      this.$router.push({ path: "/details", query: { id: item.id } });
    },
    handleClickTag(value){
      console.log('handleClickTag',value);
      this.upFinished = false; //加载中
    },
    //切换tag
    handleChangeTag(value){
      console.log('handleChangeTag',value);
      this.upFinished = false; //加载中

      this.parmas.value = value
      this.list = [];
      this.pageInfo.currentPage = 1;
      this.onLoad();
    },
    onInput(value) {
      this.parmas.name = value;
    },
    //搜索
    handleSearch() {
      this.upFinished = false; //加载中
      if (this.parmas.name == undefined || this.parmas.name == "") {
        this.onCancel();
      } else {
        this.list = [];
        this.pageInfo.currentPage = 1;
        this.onLoad();
      }
    },
    onSearch(value) {
      this.list = [];
      this.parmas.name = value;
      this.pageInfo.currentPage = 1;
      this.onLoad();
    },
    onCancel() {
      this.list = [];
      this.pageInfo.currentPage = 1;
      delete this.parmas.name;
      this.onLoad();
    }
  }
};
</script>

<style lang="scss">
    @import "@/assets/styles/mixin.scss";
    .trainingCenter {
      @include fontSize(12, 400);
      color: #454545;
      min-height: 100%;
    }

    .recommended_today {
      width: 100%;
      background: #ffffff;
      .rt_title {
        font-size: 16px;
        font-family: PingFangSC-Semibold, PingFang SC;
        font-weight: 600;
        padding: 15px 0;
        margin: 0 20px;
        border-bottom: 1px solid #e2e2e2;
      }

      .van-swipe {
        margin-left: 20px;
        padding-top: 15px;
        padding-bottom: 20px;
      }
    }

    .rt_des,
    .tc_des {
      padding-left: 0.1875rem;
      @include multiTextHide(2);
    }

    .rt_des {
      width: 9.25rem;
    }
    .tc_des {
      width: 5.9375rem;
    }

    .rt_img_box {
      width: 9.25rem;
      height: 6.1875rem;
    }

    .tc_img_box {
      width: 5.9375rem;
      height: 6.875rem;
    }
    .img_box {
      position: relative;
      border-radius: 5px;
      margin-bottom: 10px;

      .rt_img,
      .tc_img {
        position: absolute;
        left: 0;
        top: 0;
        border-radius: 5px;
      }
      .rt_img {
        @extend .rt_img_box;
      }
      .tc_img {
        @extend .tc_img_box;
      }

      .img_open {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        width: 2.5625rem;
        height: 2.5625rem;
      }
    }

    .traininds_box {
      margin-top: 20px;
      background: #ffffff;

      .van-tabs__line {
        background-color: #0091ff;
        width: 26px;
      }
    }
</style>

样式图:

样式图

参考链接: