思路:左右滑动使用swiper,上下滑动用scroll-view,swiper改变时同时改变tab并更新列表
坑点:
1. swiper高度问题,导致滑动不到最底部和最顶部
需要手动计算,减去顶部高度和底部tabbar,并且需要同时设置padding-top和paddin-botton,否则列表显示不完整
2. 由于最开始的代码是每次切换tab后都会重新请求,导致swiper还没切换成功的过程中,显示的列表错误
将代码改造成每一个tab下面的list都是隔离开的,原先使用了一个list维护不同tab
3. 每个tab下的list的加载完成状态也需要隔离开,否则导致tab1切换到tab2以后,tab2将控制加载完成的状态改为true后,返回tab1无法加载第2页了
4. 触底加载
无法使用系统的触底加载了,需要使用scroll-view的自定义上拉刷新方法
5. 下拉更新
也需要自定义,由于目前我的系统自带的还是正常的,所以还没有改造,但是体验没有scroll-view的好,因为顶部tab会遮挡下拉刷新的loading状态,后期再改造文章来源:https://www.toymoban.com/news/detail-761976.html
源码:已去除不相关代码文章来源地址https://www.toymoban.com/news/detail-761976.html
<template>
<view class="home-page">
<my-tabs :tabs="tabs" :currentTab="currentTabIndex" @change="onTabChange" :top="topStyle.total" isFixed>
</my-tabs>
<swiper class="activity-swiper" :current="currentTabIndex" interval="500" @change="onSwiperChange"
:style="{ height: `calc(100vh - ${listStyle.paddingTop} - ${listStyle.paddingBottom})`, paddingBottom: listStyle.paddingBottom, paddingTop: listStyle.paddingTop,}">
<swiper-item class="activity-swiper-item" v-for="item in tabs" :key="item.key" :item-id="item.key"
:style="{ paddingBottom: 0, paddingTop: 0 }">
<scroll-view scroll-y class="scroll-list" @scrolltolower="onBottom" :style="{ height: '100%' }"
:scroll-top="scrollTop" @scroll="scroll">
<card-activity v-for="(activity, index) in listData[item.index]" :key="activity.activityId" :data="activity"
custom-class="activity-item" @click="toActivityDetail" @share="onShare"></card-activity>
<tui-nomore v-if="isListFinished[item.index] && listData[item.index].length > 3"></tui-nomore>
</scroll-view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import {
mapState
} from 'vuex'
import {
userApi,
activityApi
} from '@/api'
import {
defaultConst,
shareTypeConst,
} from '@/const'
const tabObj = {
textList: [{
name: '我创建的',
key: 'create',
index: 0
},
{
name: '我参与的',
key: 'partake',
index: 1
},
{
name: '我关注的',
key: 'follow',
index: 2
}
],
value: {
0: 1,
1: 2,
2: 3,
}
}
export default {
data() {
return {
currentActivity: {},
tabs: tabObj.textList,
currentTabIndex: 0,
currentTabValue: 1,
listData: {
0: [], // create
1: [], // partake
2: [], // follow
},
// 每个tab的加载状态隔离开:解决切换到第三个tab加载完成后,返回第一个tab无法加载第二页的问题
isListFinished: [false, false, false],
pageIndex: 1,
isListLoading: false,
tabbarIndex: 0,
scrollTop: 0,
oldScrollTop: 0
}
},
computed: {
...mapState(['systemInfo', 'userInfo', 'showTabBarDot']),
topStyle() {
const {
statusBarHeight
} = this.systemInfo
const menuButtonInfo = wx.getMenuButtonBoundingClientRect()
const navigationBarHeight = (menuButtonInfo.top - statusBarHeight) * 2 + menuButtonInfo.height
return {
statusBarHeight,
navigationBarHeight,
total: statusBarHeight + navigationBarHeight
}
},
listStyle() {
return {
paddingTop: this.topStyle.total + 45 + 'px',
paddingBottom: '180rpx',
}
}
},
watch: {
currentTabIndex(value) {
// 首次切换tab才会重新加载数据
if (!this.listData[value].length) this.getActivityList(true)
// this.isListFinished = false
},
},
methods: {
async getActivityList(isRefresh, params, isFirst) {
const tab = this.currentTabIndex
this.showNoData = false
if (isRefresh) {
this.pageIndex = defaultConst.DEFAULT_PAGE_INDEX
this.isListFinished[this.currentTabIndex] = false
this.listData[this.currentTabIndex] = []
}
const data = {
pageIndex: this.pageIndex++,
pageSize: defaultConst.DEFAULT_PAGE_SIZE,
type: this.currentTabValue,
}
Object.keys(params || {}).map(key => {
if (params[key]) {
data[key] = params[key]
}
})
const {
hasNext,
list
} = await activityApi.getList(data)
if (tab !== this.currentTabIndex) return
if (!hasNext) {
this.isListFinished[this.currentTabIndex] = true
}
if (isRefresh) {
uni.stopPullDownRefresh()
}
this.listData[this.currentTabIndex].push(...list)
},
onTabChange({
index
}) {
this.currentTabIndex = index
this.currentTabValue = tabObj.value[index]
if (!this.listData[index].length) this.skeletonShow = true
this.goTop()
},
onSwiperChange(e) {
this.currentTabIndex = e.detail.current
this.currentTabValue = tabObj.value[e.detail.current]
if (!this.listData[e.detail.current].length) this.skeletonShow = true
this.goTop()
},
onNoticeClose() {
this.showNotice = false;
},
toActivityDetail(id) {
uni.navigateTo({
url: `/pages/activity/detail?activityId=${id}`
})
},
async onShare(activity) {
const res = await activityApi.getDetail({
activityId: activity.activityId
})
this.currentActivity = res
this.$refs.shareActivity.share()
},
toCreate() {
uni.navigateTo({
url: '/pages/activity/create'
})
},
onBottom() {
console.log('触底了')
if (!this.isListFinished[this.currentTabIndex]) {
this.getActivityList(false)
}
},
scroll(e) {
//记录scroll 位置
this.oldScrollTop = e.detail.scrollTop
},
goTop(e) {
//视图会发生重新渲染 scrollTop不会随着滚动而实时更新 所以需要手动设置 之所以不在scroll方法中设置是为了防止页面抖动
this.scrollTop = this.oldScrollTop
//当视图渲染结束 重新设置为0
wx.nextTick(() => {
this.scrollTop = 0
});
}
},
onLoad() {
this.skeletonShow = true
this.getActivityList(false)
},
onPullDownRefresh() {
this.skeletonShow = true
this.getActivityList(true)
},
}
</script>
<style lang="scss" scoped>
.activity-swiper {
&-item {
box-sizing: border-box;
padding-left: 20rpx;
padding-right: 20rpx;
}
/deep/ .activity-item {
margin-top: 20rpx;
}
}
.text-link {
color: $text-link;
}
.list-no-data-text {
color: $text-3;
}
</style>
到了这里,关于uniapp-微信小程序实现swiper左右滚动切换tab,上下滚动加载列表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!