上一节我们实现首页地图,也响应了控件点击和用户拖动地图事件。这一节我们实现一下点击立即用车扫码成功之后的页面逻辑。
这里我用了我自己微信号的二维码,你们可以用你们自己的,扫码成功后的页面是酱的:
页面分析
-
后台需要拿到开锁密码,然后显示在页面上
-
我们需要一个定时器,规定多长时间用来检查单车是否损坏,这期间如果单车故障,可以点击回首页去车辆报障,当然也就取消了本次扫码。
-
如果单车没有问题,检查时长完成后,自动跳转到计费页面
页面布局
-
<!--pages/scanresult/index.wxml-->
-
<view class="container">
-
<view class="password-title">
-
<text>开锁密码</text>
-
</view>
-
<view class="password-content">
-
<text>{{password}}</text>
-
</view>
-
<view class="tips">
-
<text>请使用密码解锁,{{time}}s后开始计费</text>
-
<view class="tips-action" bindtap="moveToWarn">
-
车辆有问题?
-
<text class="tips-href">回首页去车辆报障</text>
-
</view>
-
</view>
-
</view>
复制代码
微信小程序的页面元素有自己的一套名字,用的是weui设计风格,但是元素种类比较少,比如说<view>就代表着<div>,<text>是行内元素,<image>是图片标签等,所以页面标签这一块只要有html基础就很容易理解
页面样式
-
.container{
-
width: 100%;
-
display: flex;
-
flex-direction: column;
-
align-items: center;
-
justify-content: space-between;
-
background-color: #fff;
-
}
-
.password-title,.tips{
-
width: 100%;
-
flex: 1;
-
text-align: center;
-
padding: 60rpx 0;
-
}
-
.password-content{
-
width: 100%;
-
flex: 8;
-
text-align: center;
-
font-size: 240rpx;
-
font-weight: 900;
-
}
-
.tips{
-
font-size: 32rpx;
-
}
-
.tips .tips-action{
-
margin-top: 20rpx;
-
}
-
.tips .tips-href{
-
color: #b9dd08
-
}
复制代码
样式方面完全是css,注意这里的单位是rpx,是小程序为了自适应所有设备而设定的单位,按宽度为750px的设备计算,1rpx = 0.5px。其他比例换算可以看官方文档。
先来了解两个知识点:
-
数据渲染页面:前面我们在地图组件中设置了数据模板,然后在js里通过服务器获取数据动态给模板数据赋值,每当js数据改变,页面就会重新渲染数据。所以核心思想是数据驱动页面。我们在结构里设置了数据模板{{time}},说明这个数据是需要我们去改变的,所以先在data对象里赋予初始值9(为了调试方便,特意把时间调的很短)
-
为元素绑定事件:和传统html里不同,小程序页面为元素绑定事件不能操作元素,不然就违背了数据驱动页面的初衷,所以小程序在元素内声明一个变量如 bindtap="moveToWarn"来为指定元素绑定点击事件,然后在js里实现这个事件的功能。还可以绑定很多事件类型,更多可以查阅事件文档
先来回头看一下首页地图立即用车事件代码,如果当前没有在计费,将可以扫码,扫码成功后将会传递参数(密码和车牌号)并跳转到../scanresult/index,也就是本页面。
-
// 地图控件点击事件
-
bindcontroltap: function(e){
-
// 判断点击的是哪个控件 e.controlId代表控件的id,在页面加载时的第3步设置的id
-
switch(e.controlId){
-
// 点击定位控件
-
case 1: this.movetoPosition();
-
break;
-
// 点击立即用车,判断当前是否正在计费
-
case 2: if(this.timer === "" || this.timer === undefined){
-
// 没有在计费就扫码
-
wx.scanCode({
-
success: (res) => {
-
// 正在获取密码通知
-
wx.showLoading({
-
title: '正在获取密码',
-
mask: true
-
})
-
// 请求服务器获取密码和车号
-
wx.request({
-
url: 'https://www.easy-mock.com/mock/59098d007a878d73716e966f/ofodata/password',
-
data: {},
-
method: 'GET',
-
success: function(res){
-
// 请求密码成功隐藏等待框
-
wx.hideLoading();
-
// 携带密码和车号跳转到密码页
-
wx.redirectTo({
-
url: '../scanresult/index?password=' + res.data.data.password + '&number=' + res.data.data.number,
-
success: function(res){
-
wx.showToast({
-
title: '获取密码成功',
-
duration: 1000
-
})
-
}
-
})
-
}
-
})
-
}
-
})
-
// 当前已经在计费就回退到计费页
-
}else{
-
wx.navigateBack({
-
delta: 1
-
})
-
}
-
break;
-
// 点击保障控件,跳转到报障页
-
case 3: wx.navigateTo({
-
url: '../warn/index'
-
});
-
break;
-
// 点击头像控件,跳转到个人中心
-
case 5: wx.navigateTo({
-
url: '../my/index'
-
});
-
break;
-
default: break;
-
}
-
},
复制代码
我们在js里面写下如下代码,本页面的options就是上面传递过来的参数。试试打印出来是什么!
-
// pages/scanresult/index.js
-
Page({
-
data:{
-
time: 9 // 默认计时时长,这里设短一点,用于调试,ofo app是90s
-
},
-
// 页面加载
-
onLoad:function(options){
-
// 获取密码
-
this.setData({
-
password: options.password
-
})
-
// 设置初始计时秒数
-
let time = 9;
-
// 开始定时器
-
this.timer = setInterval(() => {
-
this.setData({
-
time: -- time // 倒计时
-
});
-
// 读完秒后携带单车号码跳转到计费页
-
if(time = 0){
-
clearInterval(this.timer)
-
wx.redirectTo({
-
url: '../billing/index?number=' + options.number
-
})
-
}
-
},1000)
-
},
-
// 点击去首页报障
-
moveToWarn: function(){
-
// 清除定时器
-
clearInterval(this.timer)
-
wx.redirectTo({
-
url: '../index/index'
-
})
-
}
-
})
复制代码
当倒计时完成之后,就应该自动跳转到计费页:
页面分析
-
后台需要拿到单车编号,并显示在页面上
-
我们需要一个计时器累加骑行事件用来计费,而且可以显示最大单位是小时
-
两个按钮:结束骑行,回到地图 。其中,点击结束骑行,关闭计时器,根据累计时长计费;点击回到地图,如果计时器已经关闭了,就关闭计费页,跳转到地图。如果计时器仍然在计时,保留当前页面,跳转到地图。
-
点击回到地图需要把计时器状态带给首页,首页做出判断,判定再次点击立即用车响应合理逻辑(已经在计费,不能重复扫码。已经停止计费了,需要重新扫码)
页面结构(看看我们哪些是数据模板?,为元素绑定了什么事件?)
-
<!--pages/billing/index.wxml-->
-
<view class="container">
-
<view class="number">
-
<text>当前单车编号: {{number}}</text>
-
</view>
-
<view class="time">
-
<view class="time-title">
-
<text>{{billing}}</text>
-
</view>
-
<view class="time-content">
-
<text>{{hours}}:{{minuters}}:{{seconds}}</text>
-
</view>
-
</view>
-
-
<view class="endride">
-
<button type="warn" disabled="{{disabled}}" bindtap="endRide">结束骑行</button>
-
<button type="primary" bindtap="moveToIndex">回到地图</button>
-
</view>
-
</view>
复制代码
页面样式
-
.container{
-
width: 100%;
-
display: flex;
-
flex-direction: column;
-
align-items: center;
-
justify-content: space-between;
-
background-color: #fff;
-
}
-
.number,.endride{
-
padding: 60rpx 0;
-
flex: 2;
-
width: 100%;
-
text-align: center;
-
}
-
.time{
-
text-align: center;
-
width: 100%;
-
flex: 6;
-
}
-
.time .time-content{
-
font-size: 100rpx;
-
}
-
.endride button{
-
width: 90%;
-
margin-top: 40rpx;
-
}
复制代码
数据逻辑(看注释更好理解哦)
-
// pages/billing/index.js
-
Page({
-
data:{
-
hours: 0,
-
minuters: 0,
-
seconds: 0,
-
billing: "正在计费"
-
},
-
// 页面加载
-
onLoad:function(options){
-
// 获取扫码成功页传过来的车牌号,再定义一个定时器
-
this.setData({
-
number: options.number,
-
timer: this.timer
-
})
-
// 初始化计时器
-
let s = 0;
-
let m = 0;
-
let h = 0;
-
// 计时开始
-
this.timer = setInterval(() => {
-
this.setData({
-
seconds: s++
-
})
-
if(s == 60){
-
s = 0;
-
m++;
-
setTimeout(() => {
-
this.setData({
-
minuters: m
-
});
-
},1000)
-
if(m == 60){
-
m = 0;
-
h++
-
setTimeout(() => {
-
this.setData({
-
hours: h
-
});
-
},1000)
-
}
-
};
-
},1000)
-
},
-
// 结束骑行,清除定时器
-
endRide: function(){
-
clearInterval(this.timer);
-
this.timer = "";
-
this.setData({
-
billing: "本次骑行耗时",
-
disabled: true
-
})
-
},
-
// 携带定时器状态回到地图
-
moveToIndex: function(){
-
// 如果定时器为空
-
if(this.timer == ""){
-
// 关闭计费页跳到地图
-
wx.redirectTo({
-
url: '../index/index'
-
})
-
// 保留计费页跳到地图,带上计时器状态
-
}else{
-
wx.navigateTo({
-
url: '../index/index?timer=' + this.timer
-
})
-
}
-
}
-
})
页面分析的第4步,主要实现在moveToIndex函数里。结束骑行之后,设置定时器值为空,当点击回到地图时判断计时器的状态(值是否为空)。如果为空,关闭计费页,结束本次骑行。如果不为空,携带定时器状态跳转到首页,首页立即用车点击事件就会对传过来的参数(计时器状态)响应合理逻辑。再回去上面看一下立即用车的判断条件,当本页面传过去的计时器不满足条件时,我们在地图首页点击立即用车将会回到本页面
其他章节
微信小程序开发之OFO共享单车——扫码
微信小程序开发之OFO共享单车——单车报障页
微信小程序开发之OFO共享单车——个人中心页
微信小程序开发之OFO共享单车——钱包与充值