在上一篇文章,讲解了再微信小程序中如何实现页面上下滚动、左右滑动。但是,此处有2个缺陷。
当有多少个可以滑动的页面时,就会渲染多少个组件
当快速的左右滑动时,swiper 会出现卡死(无限循环滑动)的现象
那么我们可以考虑在每次渲染 swiper-item 时,最多渲染 3 个,动态生成可滑动的页面,于是就做出了如下效果的页面。

最多只有 3 个 swiper-item,在左右滑动时,由于下标不时的轮询,而且 swiper 的自动切换并非是无缝切换的,故在滑动 swiper-item 时,会出现向右滑动产生向左的动画效果,向左滑动产生向右的动画效果。

├── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── pretest │ ├── pretest.js │ ├── pretest.json │ ├── pretest.wxml │ └── pretest.wxss ├── test│ ├── test.js │ ├── test.json │ ├── test.wxml │ └── test.wxss
当有多少个可以滑动的页面时,就会渲染多少个组件
pretest.js
Component({
data: {
quesArr: [
{
currentGcolor: '#ccc',
currentGscore: 3,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '单选题',
id: 0,
},
{
currentGcolor: '#ccc',
currentGscore: 0,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '多选题',
id: 1,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题1',
id: 2,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题2',
id: 3,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题3',
id: 4,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题4',
id: 5,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题5',
id: 6,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题6',
id: 7,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题7',
id: 8,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题8',
id: 9,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题9',
id: 10,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题10',
id: 11,
},
{
currentGcolor: '#0AC013',
currentGscore: 5,
currentFcolor: '#0AC013',
currentFscore: 5,
typeName: '判断题11',
id: 12,
},
]
},
methods: {
onTest (e) {
const currentTab = e.currentTarget.dataset.index const quesArr = this.data.quesArr
wx.navigateTo({
url: '/pages/test/test',
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { currentTab, quesArr})
}
})
}
},})
pretest.json
{
"usingComponents": {}}123
pretest.wxml
<view class="p_con">
<view wx:for="{{quesArr}}" wx:key="id" class="p_item" wx:for-index="idx" bindtap="onTest" data-index="{{idx}}">
{{idx + 1}}-{{item.typeName}} </view></view>
pretest.wxss
.p_con{
padding: 30rpx 26rpx;
box-sizing: border-box;}.p_item{
padding: 20rpx;
margin-bottom: 20rpx;
border-bottom: 2rpx solid #e8e8e8;}.p_item:last-child{
margin-bottom: 0;}
代码如下(示例):
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')import ssl
ssl._create_default_https_context = ssl._create_unverified_context
页面效果

test.js
let eventChannelComponent({
behaviors: [require('miniprogram-computed')],
computed: {
// 待渲染的数组
rQuesArr (data) {
const {currentTab, quesArr} = data return quesArr.filter((v, i) => i <= currentTab + 1 && i >= currentTab - 1)
},
quesLen (data) {
return data.quesArr.length },
curQuesObj (data) {
return data.quesArr[data.currentTab]
},
quesTitle (data) {
const {curQuesObj} = data return curQuesObj ? curQuesObj.typeName : ''
},
currentGcolor (data) {
const {curQuesObj} = data return curQuesObj ? curQuesObj.currentGcolor : ''
},
currentGscore (data) {
const {curQuesObj} = data return curQuesObj ? curQuesObj.currentGscore : ''
},
currentFcolor (data) {
const {curQuesObj} = data return curQuesObj ? curQuesObj.currentFcolor : ''
},
currentFscore (data) {
const {curQuesObj} = data return curQuesObj ? curQuesObj.currentFscore : ''
},
},
data: {
quesArr: [],
// 待渲染的数组下标
rCurrentTab: 0,
// 真实数组下标
currentTab: 0,
},
/*组件生命周期*/
lifetimes: {
ready: function () {
eventChannel = this.getOpenerEventChannel()
eventChannel.on('acceptDataFromOpenerPage', (data) => {
const {currentTab, quesArr} = data this.setData({
currentTab,
quesArr })
})
},
},
methods: {
switchTab (e){
if (e.detail.source === 'touch') {
let cur = e.detail.current;
let ctab = this.data.currentTab // 下标为0时,禁止向左滑动
if (cur === 0 && this.data.currentTab === 0) {
return
}
// 下标为最大值时,禁止向右滑动
if (cur === this.data.rQuesArr.length - 1 && this.data.currentTab === this.data.quesLen - 1) {
return
}
if (this.data.rCurrentTab === cur) {
if (this.data.currentTab === this.data.quesLen - 1) {
return
}
if (cur === this.data.rQuesArr.length - 1) {
// 向右滑动
cur = 0
ctab = this.data.currentTab + 1
} else if (cur === 0) {
// 向左滑动
cur = this.data.rQuesArr.length - 1
ctab = this.data.currentTab - 1
}
} else if (this.data.rCurrentTab < cur) {
ctab = ctab + 1
} else {
ctab = ctab - 1
}
this.setData({
currentTab: ctab })
this.setData({
rCurrentTab: this.getCur(cur)
})
}
},
getCur (cur) {
if (this.data.currentTab === this.data.quesLen - 1) {
return this.data.rQuesArr.length - 1
} else if (this.data.currentTab === 0) {
return 0
}
return cur }
},})
test.json
{
"usingComponents": {}}
test.wxml
<view class="top_wrap box flexbox_y flexbox_between">
{{quesTitle}}</view><view class="center_wrap maxw ova">
<swiper current="{{rCurrentTab}}" bindanimationfinish="switchTab" class="maxh">
<swiper-item wx:for="{{rQuesArr}}" wx:for-index="idx" wx:key="subNum" duration="0">
<scroll-view scroll-y class="maxh">
<view class="center_view box">
<view class="item">{{idx}}-1</view>
<view class="item">2</view>
<view class="item">3</view>
<view class="item">4</view>
<view class="item">5</view>
<view class="item">6</view>
<view class="item">1</view>
<view class="item">2</view>
<view class="item">3</view>
<view class="item">4</view>
<view class="item">5</view>
<view class="item">6</view>
</view>
</scroll-view>
</swiper-item>
</swiper></view><view class="foot_wrap box flexbox_y flexbox_between">
<view>得分:<text style="color: {{currentGcolor}}">{{currentGscore}}</text><text style="color: {{currentFcolor}}">/{{currentFscore}}</text></view>
<view>{{currentTab + 1}}<text class="sch-ccc">/{{quesLen}}</text></view></view>
test.wxss
page{
position: static;}.top_wrap{
height: 106rpx;
color: #333;
padding: 0 36rpx;
border-bottom: 2rpx solid #E8E8E8;
position: fixed;
top: 0;
width: 100%;
z-index: 1;}.center_wrap{
position: fixed;
top: 108rpx;
bottom: 120rpx;
z-index: -1;}.center_wrap .item{
height: 300rpx;
margin: 15rpx;}.center_view{
padding: 30rpx 36rpx;}.foot_wrap{
height: 118rpx;
color: #333;
padding: 0 36rpx;
border-top: 2rpx solid #E8E8E8;
position: fixed;
bottom: 0;
width: 100%;
z-index: 1;}.flexbox_y {
display: flex;
align-items: center;}.flexbox_between{
display: flex;
justify-content: space-between;}.maxh{
height: 100%;}.maxw{
width: 100%;}.box{
box-sizing: border-box;}.sch-ccc{
color: #ccc;}.ova{
overflow: auto;}
页面效果

步骤如下:
将 swiper 的 bindchange 函数替换成 bindanimationfinish函数

在改变 swiper 的 current 值前检测 source 字段来判断是否是由于用户触摸引起

if (e.detail.source === 'touch') {}12
此处的左右滑动虽然解决了渲染 swiper-item 过多的问题,但是 swiper 组件并不能良好的无缝切入下一个页面,每次滑动的效果不尽如意。
来源:https://www.freesion.com/article/23531327806/