解决思路:页面只展示3个swiper-item组件(小程序视频轮播插件受到的启发),每次轮播变化,都截取总数据里面的3条进行展示
观察规律:画了个简单草图,大家可以看下,每次轮播索引变化后,计算出当前索引、前一个索引值、后一个索引值,以及分别对应到数据列表上的索引和值
代码实现
<template>
<view class="index-box">
<swiper class="swipe" :circular="circular" :current="swipeActiveIndex" @change="swipeChange">
<swiper-item v-for="(item, index) in swipeList" :key="index">
<view class="swipe-item">{{ item }}</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
export default {
data() {
return {
circular: true, // 是否可以循环滚动
swipeActiveIndex: 0, // 当前轮播图激活索引
currentIndex: 0, // 当前展示数据在列表中的索引值
swipeLength: 3, // 总的轮播图数量
dataList: [1, 2, 3, 4, 5, 6, 7] // 数据列表
}
},
computed: {
swipeList() {
// 获取当前值、下一个值、上一个值
let currentValue = this.dataList[this.currentIndex]
let nextValue = this.dataList[this.getDataIndex(this.currentIndex + 1)]
let prevValue = this.dataList[this.getDataIndex(this.currentIndex - 1)]
// 获取当前轮播索引对应的值、下个索引对应的值、上个索引对应的值
let list = new Array(3)
list[this.swipeActiveIndex] = currentValue
list[this.getSwipeIndex(this.swipeActiveIndex + 1)] = nextValue
list[this.getSwipeIndex(this.swipeActiveIndex - 1)] = prevValue
return list
}
},
methods: {
swipeChange(event) {
let current = Number(event.detail.current)
if ([1, 1 - this.swipeLength].includes(current - this.swipeActiveIndex)) {
// 向左滑动
this.currentIndex = this.getDataIndex(this.currentIndex + 1)
} else {
// 向右滑动
this.currentIndex = this.getDataIndex(this.currentIndex - 1)
}
this.swipeActiveIndex = current
},
// 获取当前数据列表的索引
getDataIndex(index) {
if (index < 0) {
// 小于零,返回数据列表末尾索引
return this.dataList.length - 1
} else if (index >= this.dataList.length) {
// 等于(或大于,一般不会)数据列表长度,返回数据首位索引
return 0
} else {
return index
}
},
getSwipeIndex(index) {
if (index < 0) {
return this.swipeLength - 1
} else if (index >= this.swipeLength) {
return 0
} else {
return index
}
}
}
}
</script>
<style scoped lang="scss">
.index-box {
width: 100%;
.swipe {
width: 100%;
height: 300rpx;
&-item {
display: flex;
width: 100%;
height: 100%;
font-size: 80rpx;
color: #fff;
background: #222;
align-items: center;
justify-content: center;
}
}
}
</style>
<template>
<view class="index-box u-safe-area-inset-bottom">
<c-space />
<swiper
class="swipe"
:current="currentSwipeIndex"
:circular="circular"
@animationfinish="swipeChange"
>
<swiper-item v-for="(item, index) in swipeList" :key="index">
<answer-item :item="item" @next="nextSwipe" />
</swiper-item>
</swiper>
<view class="submit-btn">
<view class="submit-btn__wrap" @click="onSubmit">提交</view>
</view>
<view class="paging">{{ currentIndex + 1 }} / {{ dataList.length }}</view>
</view>
</template>
<script>
import AnswerItem from './components/AnswerItem'
import { mapState } from 'vuex'
export default {
components: { AnswerItem },
data() {
return {
currentSwipeIndex: 0,
circular: true, // 是否可以循环滚动
swipeActiveIndex: 0, // 当前轮播图激活索引
currentIndex: 0, // 当前展示数据在列表中的索引值
swipeLength: 3, // 总的轮播图数量
// dataList: [1, 2, 3, 4, 5, 6, 7], // 数据列表
}
},
computed: {
...mapState({
dataList: (state) => state.vuex_assess_topic,
answerList: (state) => state.vuex_assess_answer,
assessInfo: (state) => state.vuex_assess_info,
assessEmpty: (state) => state.vuex_assess_empty,
}),
swipeList() {
// 获取当前值、下一个值、上一个值
let currentValue = this.dataList[this.currentIndex]
let nextValue = this.dataList[this.getDataIndex(this.currentIndex + 1)]
let prevValue = this.dataList[this.getDataIndex(this.currentIndex - 1)]
// 获取当前轮播索引对应的值、下个索引对应的值、上个索引对应的值
let list = new Array(3)
list[this.swipeActiveIndex] = currentValue
list[this.getSwipeIndex(this.swipeActiveIndex + 1)] = nextValue
list[this.getSwipeIndex(this.swipeActiveIndex - 1)] = prevValue
return list
},
},
onLoad() {
uni.setNavigationBarTitle({
title: this.assessInfo.title,
})
},
methods: {
swipeChange(event) {
let current = Number(event.detail.current)
if ([1, 1 - this.swipeLength, 0].includes(current - this.swipeActiveIndex)) {
this.currentIndex = this.getDataIndex(this.currentIndex + 1)
} else {
this.currentIndex = this.getDataIndex(this.currentIndex - 1)
}
this.swipeActiveIndex = current
},
nextSwipe() {
setTimeout(() => {
this.currentSwipeIndex = this.getSwipeIndex(this.swipeActiveIndex + 1)
}, 600)
},
// 获取当前数据列表的索引
getDataIndex(index) {
if (index < 0) {
// 小于零,返回数据列表末尾索引
return this.dataList.length - 1
} else if (index >= this.dataList.length) {
// 等于(或大于,一般不会)数据列表长度,返回数据首位索引
return 0
} else {
return index
}
},
getSwipeIndex(index) {
if (index < 0) {
return this.swipeLength - 1
} else if (index >= this.swipeLength) {
return 0
} else {
return index
}
},
/*提交*/
onSubmit() {
const valid = this.answerList.some((item) => !item)
if (valid) {
this.$toast('请完成所有题目')
return
}
this.$loading()
this.$request
.post('study.subAnswer', {
study_id: this.assessInfo.id,
answer: this.answerList.map((item) => (item === this.assessEmpty ? '' : item)),
})
.then(() => {
this.$hide()
this.$linkTo('/package/echarts/assess-result/index')
})
.catch((err) => {
this.$toast(err)
})
},
},
}
</script>
<style>
page {
width: 100%;
height: 100%;
}
</style>
<style scoped lang="scss">
@import 'static/styles/mixin';
.index-box {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background: #f7f7f7;
.swipe {
width: 100%;
flex: 1;
overflow: hidden;
}
.paging {
display: flex;
width: 100%;
height: 112rpx;
font-size: 26rpx;
align-items: center;
justify-content: center;
}
.submit-btn {
width: 100%;
padding: 0 30rpx;
&__wrap {
@include flex-row-center;
width: 100%;
height: 100rpx;
font-size: 30rpx;
font-weight: bold;
color: #fff;
background: linear-gradient(90deg, #ff6155, #fb1a26);
border-radius: 16rpx;
}
}
.submit-disabled {
.submit-btn__wrap {
position: relative;
&::after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.2);
border-radius: 16rpx;
content: '';
}
}
}
}
</style>