系列文章目录
前言
在上一篇文章,讲解了再微信小程序中如何实现页面上下滚动、左右滑动。但是,此处有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
解决问题1
当有多少个可以滑动的页面时,就会渲染多少个组件
1.pretest页面
- 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": {}
}
- 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
- 页面效果
2.test页面
- test.js
let eventChannel
Component({
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;
}
- 页面效果
解决问题2
步骤如下:
-
将
swiper
的bindchange
函数替换成bindanimationfinish
函数
-
在改变
swiper
的current
值前检测source
字段来判断是否是由于用户触摸引起
if (e.detail.source === 'touch') {
}
总结
此处的左右滑动虽然解决了渲染 swiper-item
过多的问题,但是 swiper
组件并不能良好的无缝切入下一个页面,每次滑动的效果不尽如意。
各位看官,你们有什么思路呢?欢迎留言!