运用vant实现下拉刷新上拉加载功能
功能:
- 列表实现下拉刷新和上拉加载
- Tab选项卡滑动到顶部时悬停头部
- Tab实现滑动切换
前提:
引入了 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>
样式图:
参考链接: