赞
踩
思路:左右滑动使用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状态,后期再改造
源码:已去除不相关代码
- <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>

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。