微信小程序開(kāi)發(fā)之OFO共享單車(chē),微信小程序掃描二維碼
2017-12-20
導(dǎo)讀:上一節(jié)我們實(shí)現(xiàn)首頁(yè)地圖,也響應(yīng)了控件點(diǎn)擊和用戶拖動(dòng)地圖事件。這一節(jié)我們實(shí)現(xiàn)一下點(diǎn)擊立即用車(chē)掃碼成功之后的頁(yè)面邏輯。 這里我用了我自己微信號(hào)的二維碼,你們可以用你們自...
上一節(jié)我們實(shí)現(xiàn)首頁(yè)地圖,也響應(yīng)了控件點(diǎn)擊和用戶拖動(dòng)地圖事件。這一節(jié)我們實(shí)現(xiàn)一下點(diǎn)擊立即用車(chē)掃碼成功之后的頁(yè)面邏輯。
這里我用了我自己微信號(hào)的二維碼,你們可以用你們自己的,掃碼成功后的頁(yè)面是醬的:
頁(yè)面分析
頁(yè)面布局
復(fù)制代碼
微信小程序的頁(yè)面元素有自己的一套名字,用的是weui設(shè)計(jì)風(fēng)格,但是元素種類(lèi)比較少,比如說(shuō)<view>就代表著<div>,<text>是行內(nèi)元素,<image>是圖片標(biāo)簽等,所以頁(yè)面標(biāo)簽這一塊只要有html基礎(chǔ)就很容易理解
頁(yè)面樣式
復(fù)制代碼
樣式方面完全是css,注意這里的單位是rpx,是小程序?yàn)榱俗赃m應(yīng)所有設(shè)備而設(shè)定的單位,按寬度為750px的設(shè)備計(jì)算,1rpx = 0.5px。其他比例換算可以看官方文檔。
先來(lái)了解兩個(gè)知識(shí)點(diǎn):
先來(lái)回頭看一下首頁(yè)地圖立即用車(chē)事件代碼,如果當(dāng)前沒(méi)有在計(jì)費(fèi),將可以掃碼,掃碼成功后將會(huì)傳遞參數(shù)(密碼和車(chē)牌號(hào))并跳轉(zhuǎn)到../scanresult/index,也就是本頁(yè)面。
復(fù)制代碼
我們?cè)趈s里面寫(xiě)下如下代碼,本頁(yè)面的options就是上面?zhèn)鬟f過(guò)來(lái)的參數(shù)。試試打印出來(lái)是什么!
復(fù)制代碼
當(dāng)?shù)褂?jì)時(shí)完成之后,就應(yīng)該自動(dòng)跳轉(zhuǎn)到計(jì)費(fèi)頁(yè):
頁(yè)面分析
頁(yè)面結(jié)構(gòu)(看看我們哪些是數(shù)據(jù)模板?,為元素綁定了什么事件?)
復(fù)制代碼
頁(yè)面樣式
復(fù)制代碼
數(shù)據(jù)邏輯(看注釋更好理解哦)
頁(yè)面分析的第4步,主要實(shí)現(xiàn)在moveToIndex函數(shù)里。結(jié)束騎行之后,設(shè)置定時(shí)器值為空,當(dāng)點(diǎn)擊回到地圖時(shí)判斷計(jì)時(shí)器的狀態(tài)(值是否為空)。如果為空,關(guān)閉計(jì)費(fèi)頁(yè),結(jié)束本次騎行。如果不為空,攜帶定時(shí)器狀態(tài)跳轉(zhuǎn)到首頁(yè),首頁(yè)立即用車(chē)點(diǎn)擊事件就會(huì)對(duì)傳過(guò)來(lái)的參數(shù)(計(jì)時(shí)器狀態(tài))響應(yīng)合理邏輯。再回去上面看一下立即用車(chē)的判斷條件,當(dāng)本頁(yè)面?zhèn)鬟^(guò)去的計(jì)時(shí)器不滿足條件時(shí),我們?cè)诘貓D首頁(yè)點(diǎn)擊立即用車(chē)將會(huì)回到本頁(yè)面
其他章節(jié)
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——掃碼
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——單車(chē)報(bào)障頁(yè)
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——個(gè)人中心頁(yè)
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——錢(qián)包與充值
這里我用了我自己微信號(hào)的二維碼,你們可以用你們自己的,掃碼成功后的頁(yè)面是醬的:
頁(yè)面分析
- 后臺(tái)需要拿到開(kāi)鎖密碼,然后顯示在頁(yè)面上
- 我們需要一個(gè)定時(shí)器,規(guī)定多長(zhǎng)時(shí)間用來(lái)檢查單車(chē)是否損壞,這期間如果單車(chē)故障,可以點(diǎn)擊回首頁(yè)去車(chē)輛報(bào)障,當(dāng)然也就取消了本次掃碼。
- 如果單車(chē)沒(méi)有問(wèn)題,檢查時(shí)長(zhǎng)完成后,自動(dòng)跳轉(zhuǎn)到計(jì)費(fèi)頁(yè)面
頁(yè)面布局
- <!--pages/scanresult/index.wxml-->
- <view class="container">
- <view class="password-title">
- <text>開(kāi)鎖密碼</text>
- </view>
- <view class="password-content">
- <text>{{password}}</text>
- </view>
- <view class="tips">
- <text>請(qǐng)使用密碼解鎖,{{time}}s后開(kāi)始計(jì)費(fèi)</text>
- <view class="tips-action" bindtap="moveToWarn">
- 車(chē)輛有問(wèn)題?
- <text class="tips-href">回首頁(yè)去車(chē)輛報(bào)障</text>
- </view>
- </view>
- </view>
微信小程序的頁(yè)面元素有自己的一套名字,用的是weui設(shè)計(jì)風(fēng)格,但是元素種類(lèi)比較少,比如說(shuō)<view>就代表著<div>,<text>是行內(nèi)元素,<image>是圖片標(biāo)簽等,所以頁(yè)面標(biāo)簽這一塊只要有html基礎(chǔ)就很容易理解
頁(yè)面樣式
- .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,是小程序?yàn)榱俗赃m應(yīng)所有設(shè)備而設(shè)定的單位,按寬度為750px的設(shè)備計(jì)算,1rpx = 0.5px。其他比例換算可以看官方文檔。
先來(lái)了解兩個(gè)知識(shí)點(diǎn):
- 數(shù)據(jù)渲染頁(yè)面:前面我們?cè)诘貓D組件中設(shè)置了數(shù)據(jù)模板,然后在js里通過(guò)服務(wù)器獲取數(shù)據(jù)動(dòng)態(tài)給模板數(shù)據(jù)賦值,每當(dāng)js數(shù)據(jù)改變,頁(yè)面就會(huì)重新渲染數(shù)據(jù)。所以核心思想是數(shù)據(jù)驅(qū)動(dòng)頁(yè)面。我們?cè)诮Y(jié)構(gòu)里設(shè)置了數(shù)據(jù)模板{{time}},說(shuō)明這個(gè)數(shù)據(jù)是需要我們?nèi)ジ淖兊?,所以先在data對(duì)象里賦予初始值9(為了調(diào)試方便,特意把時(shí)間調(diào)的很短)
- 為元素綁定事件:和傳統(tǒng)html里不同,小程序頁(yè)面為元素綁定事件不能操作元素,不然就違背了數(shù)據(jù)驅(qū)動(dòng)頁(yè)面的初衷,所以小程序在元素內(nèi)聲明一個(gè)變量如 bindtap="moveToWarn"來(lái)為指定元素綁定點(diǎn)擊事件,然后在js里實(shí)現(xiàn)這個(gè)事件的功能。還可以綁定很多事件類(lèi)型,更多可以查閱事件文檔
先來(lái)回頭看一下首頁(yè)地圖立即用車(chē)事件代碼,如果當(dāng)前沒(méi)有在計(jì)費(fèi),將可以掃碼,掃碼成功后將會(huì)傳遞參數(shù)(密碼和車(chē)牌號(hào))并跳轉(zhuǎn)到../scanresult/index,也就是本頁(yè)面。
- // 地圖控件點(diǎn)擊事件
- bindcontroltap: function(e){
- // 判斷點(diǎn)擊的是哪個(gè)控件 e.controlId代表控件的id,在頁(yè)面加載時(shí)的第3步設(shè)置的id
- switch(e.controlId){
- // 點(diǎn)擊定位控件
- case 1: this.movetoPosition();
- break;
- // 點(diǎn)擊立即用車(chē),判斷當(dāng)前是否正在計(jì)費(fèi)
- case 2: if(this.timer === "" || this.timer === undefined){
- // 沒(méi)有在計(jì)費(fèi)就掃碼
- wx.scanCode({
- success: (res) => {
- // 正在獲取密碼通知
- wx.showLoading({
- title: '正在獲取密碼',
- mask: true
- })
- // 請(qǐng)求服務(wù)器獲取密碼和車(chē)號(hào)
- wx.request({
- url: 'https://www.easy-mock.com/mock/59098d007a878d73716e966f/ofodata/password',
- data: {},
- method: 'GET',
- success: function(res){
- // 請(qǐng)求密碼成功隱藏等待框
- wx.hideLoading();
- // 攜帶密碼和車(chē)號(hào)跳轉(zhuǎn)到密碼頁(yè)
- wx.redirectTo({
- url: '../scanresult/index?password=' + res.data.data.password + '&number=' + res.data.data.number,
- success: function(res){
- wx.showToast({
- title: '獲取密碼成功',
- duration: 1000
- })
- }
- })
- }
- })
- }
- })
- // 當(dāng)前已經(jīng)在計(jì)費(fèi)就回退到計(jì)費(fèi)頁(yè)
- }else{
- wx.navigateBack({
- delta: 1
- })
- }
- break;
- // 點(diǎn)擊保障控件,跳轉(zhuǎn)到報(bào)障頁(yè)
- case 3: wx.navigateTo({
- url: '../warn/index'
- });
- break;
- // 點(diǎn)擊頭像控件,跳轉(zhuǎn)到個(gè)人中心
- case 5: wx.navigateTo({
- url: '../my/index'
- });
- break;
- default: break;
- }
- },
我們?cè)趈s里面寫(xiě)下如下代碼,本頁(yè)面的options就是上面?zhèn)鬟f過(guò)來(lái)的參數(shù)。試試打印出來(lái)是什么!
- // pages/scanresult/index.js
- Page({
- data:{
- time: 9 // 默認(rèn)計(jì)時(shí)時(shí)長(zhǎng),這里設(shè)短一點(diǎn),用于調(diào)試,ofo app是90s
- },
- // 頁(yè)面加載
- onLoad:function(options){
- // 獲取密碼
- this.setData({
- password: options.password
- })
- // 設(shè)置初始計(jì)時(shí)秒數(shù)
- let time = 9;
- // 開(kāi)始定時(shí)器
- this.timer = setInterval(() => {
- this.setData({
- time: -- time // 倒計(jì)時(shí)
- });
- // 讀完秒后攜帶單車(chē)號(hào)碼跳轉(zhuǎn)到計(jì)費(fèi)頁(yè)
- if(time = 0){
- clearInterval(this.timer)
- wx.redirectTo({
- url: '../billing/index?number=' + options.number
- })
- }
- },1000)
- },
- // 點(diǎn)擊去首頁(yè)報(bào)障
- moveToWarn: function(){
- // 清除定時(shí)器
- clearInterval(this.timer)
- wx.redirectTo({
- url: '../index/index'
- })
- }
- })
當(dāng)?shù)褂?jì)時(shí)完成之后,就應(yīng)該自動(dòng)跳轉(zhuǎn)到計(jì)費(fèi)頁(yè):

頁(yè)面分析
- 后臺(tái)需要拿到單車(chē)編號(hào),并顯示在頁(yè)面上
- 我們需要一個(gè)計(jì)時(shí)器累加騎行事件用來(lái)計(jì)費(fèi),而且可以顯示最大單位是小時(shí)
- 兩個(gè)按鈕:結(jié)束騎行,回到地圖 。其中,點(diǎn)擊結(jié)束騎行,關(guān)閉計(jì)時(shí)器,根據(jù)累計(jì)時(shí)長(zhǎng)計(jì)費(fèi);點(diǎn)擊回到地圖,如果計(jì)時(shí)器已經(jīng)關(guān)閉了,就關(guān)閉計(jì)費(fèi)頁(yè),跳轉(zhuǎn)到地圖。如果計(jì)時(shí)器仍然在計(jì)時(shí),保留當(dāng)前頁(yè)面,跳轉(zhuǎn)到地圖。
- 點(diǎn)擊回到地圖需要把計(jì)時(shí)器狀態(tài)帶給首頁(yè),首頁(yè)做出判斷,判定再次點(diǎn)擊立即用車(chē)響應(yīng)合理邏輯(已經(jīng)在計(jì)費(fèi),不能重復(fù)掃碼。已經(jīng)停止計(jì)費(fèi)了,需要重新掃碼)
頁(yè)面結(jié)構(gòu)(看看我們哪些是數(shù)據(jù)模板?,為元素綁定了什么事件?)
- <!--pages/billing/index.wxml-->
- <view class="container">
- <view class="number">
- <text>當(dāng)前單車(chē)編號(hào): {{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">結(jié)束騎行</button>
- <button type="primary" bindtap="moveToIndex">回到地圖</button>
- </view>
- </view>
頁(yè)面樣式
- .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;
- }
數(shù)據(jù)邏輯(看注釋更好理解哦)
- // pages/billing/index.js
- Page({
- data:{
- hours: 0,
- minuters: 0,
- seconds: 0,
- billing: "正在計(jì)費(fèi)"
- },
- // 頁(yè)面加載
- onLoad:function(options){
- // 獲取掃碼成功頁(yè)傳過(guò)來(lái)的車(chē)牌號(hào),再定義一個(gè)定時(shí)器
- this.setData({
- number: options.number,
- timer: this.timer
- })
- // 初始化計(jì)時(shí)器
- let s = 0;
- let m = 0;
- let h = 0;
- // 計(jì)時(shí)開(kāi)始
- 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)
- },
- // 結(jié)束騎行,清除定時(shí)器
- endRide: function(){
- clearInterval(this.timer);
- this.timer = "";
- this.setData({
- billing: "本次騎行耗時(shí)",
- disabled: true
- })
- },
- // 攜帶定時(shí)器狀態(tài)回到地圖
- moveToIndex: function(){
- // 如果定時(shí)器為空
- if(this.timer == ""){
- // 關(guān)閉計(jì)費(fèi)頁(yè)跳到地圖
- wx.redirectTo({
- url: '../index/index'
- })
- // 保留計(jì)費(fèi)頁(yè)跳到地圖,帶上計(jì)時(shí)器狀態(tài)
- }else{
- wx.navigateTo({
- url: '../index/index?timer=' + this.timer
- })
- }
- }
- })
頁(yè)面分析的第4步,主要實(shí)現(xiàn)在moveToIndex函數(shù)里。結(jié)束騎行之后,設(shè)置定時(shí)器值為空,當(dāng)點(diǎn)擊回到地圖時(shí)判斷計(jì)時(shí)器的狀態(tài)(值是否為空)。如果為空,關(guān)閉計(jì)費(fèi)頁(yè),結(jié)束本次騎行。如果不為空,攜帶定時(shí)器狀態(tài)跳轉(zhuǎn)到首頁(yè),首頁(yè)立即用車(chē)點(diǎn)擊事件就會(huì)對(duì)傳過(guò)來(lái)的參數(shù)(計(jì)時(shí)器狀態(tài))響應(yīng)合理邏輯。再回去上面看一下立即用車(chē)的判斷條件,當(dāng)本頁(yè)面?zhèn)鬟^(guò)去的計(jì)時(shí)器不滿足條件時(shí),我們?cè)诘貓D首頁(yè)點(diǎn)擊立即用車(chē)將會(huì)回到本頁(yè)面
其他章節(jié)
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——掃碼
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——單車(chē)報(bào)障頁(yè)
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——個(gè)人中心頁(yè)
微信小程序開(kāi)發(fā)之OFO共享單車(chē)——錢(qián)包與充值
第二部分:如何開(kāi)通一個(gè)小商店