WePY 在手機充值小程序中的應用與實踐


wepyjs 發布了兩個月了,中間經歷了很多版本更新,也慢慢開始有一些用戶選擇 wepyjs 作為開發框架來開發小程序,比如一些線上小程序。

以及一些來自網上的 wepyjs 的相關資源:

demo源碼: one圖書管理系統

組件:圖表控件

因此我也將手機充值小程序在開發過程中 wepyjs 的應用心得分享出來,可以參照對比與傳統小程序開發上的差異。

說明:本文不涉及到 wepyjs 的使用與說明,如果需要請參看我的另一篇文章 ”打造小程序組件化開發框架” 或直接參看wepyjs 項目地址

組件化

開發時期望邏輯代碼按照業務模塊划分,從視覺圖上來看,首頁可以分為五個模塊,分別是:

  • 輸入框:Input

  • 下拉歷史記錄:History

  • 充話費:Mobile

  • 充流量:Traffic

  • 右下角菜單:Menu

如下圖:

在原生小程序中,可以使用小程序的模板特性來達到模塊化區別的目地,如下:

<!-- index.wxml --> <import src="components/input"/> <import src="components/history" /> <import src="components/mobile" /> <import src="components/traffic" /> <import src="components/menu" /> <view class="pageIndex"> <template is="comInput" data="{{number}}" /> <template is="comMobile" data="{{mobileList}}" /> <template is="comTraffic" data="{{trafficList}}" /> <template is="comMenu"/> </view> // index.js var Input = require('./components/input'); var History = require('./components/history'); var Mobile = require('./components/mobile'); var Traffic = require('./components/traffic'); var Menu = require('./components/menu'); var MyApp = { Input: Input, History: History, Mobile: Mobile, Traffic: Traffic Menu: Menu }; // .... Page(MyApp); 

如此,便可以業務模塊去組織自己的代碼。

小程序的js模塊與wxml模塊並無直接關聯,在數據或是事件的命名上需要使用前綴或者是命名空間的方式區分,以防沖突。

比如在Mobile模塊中有一個商品列表list,並且每個商品都有一個點擊下單事件submit。因此在開發時需要使用mobileList,mobileSubmit或者Mobile.list,Mobile.submit以防止與Traffic模塊沖突,代碼如下:


<block wx:for-items="{{mobileList}}"> <view class="goods mobile" bindtap="mobileSubmit" data-id="{{item.id}}" data-amount="{{item.amount}}" data-type="{{item.type}}"> {{item.price}} </view> </block> 

使用 wepyjs 直接讓小程序能夠支持組件化開發。讓小程序開發能夠像 Vue,React 一樣使用自定義組件開發。因此首頁index.wpy 中可以寫成這樣:


<template> <view class="pageIndex"> <cinput :number.sync="number" /> <mobile /> <traffic /> <menu /> </view> </template> <script> import wepy from 'wepy'; import Input from '../components/input'; import Menu from '../components/menu'; import Mobile from '../components/mobile'; import Traffic from '../components/traffic'; export default class Index extends wepy.page { components = { menu: Menu, mobile: Mobile, traffic: Traffic, cinput: Input }; data = { number: '' }; } </script> 

在充話費組件components/mobile.wpy中關鍵代碼如下:


<template> .... <block wx:for-items="{{list}}"> <view class="goods mobile" bindtap="submit({{item.id}}, {{item.amount}}, {{item.type}})"> {{item.price}} </view> </block> .... </template> <script> import wepy from 'wepy'; export default class Mobile extends wepy.component { data = { list: [] }; methods = { submit (id, amount, type) { } }; onLoad () { // load list; } } </script> 

對比於之間的代碼,我們不用再關心是mobileList還是trafficList。無論是Mobile組件還是Traffic組件,都有自己的listsubmit方法。保證了組件與組件之間數據的隔離。

Mixin 混合

混合是對組件的復用性的一種補充,使用Mixin可以很靈活的復用不同組件中的相同部分。

比如,為了做好用戶體驗細節的優化,在面額列表的滾動時加入了陰影控制。當滾到最左邊時,左邊無陰影,滾動到最右邊時,右邊無陰影,滾動到中間時兩邊都出現陰影。如下圖:

陰影由兩個透明漸變效果的樣式決定:left-shadow,right-shadow。

對於Mobile組件和Traffic組件來說,這一功能是兩者共有特性,因此可以使用Mixin來實現。

創建Mixin文件mixin/scroll.js

import wepy from 'wepy'; export default class ScrollMixin extends wepy.mixin { data = { shadow: 'left-shadow' }; methods = { scroll: function (e) { this.shadow = 'left-shadow right-shadow'; }, scrollLeft: function (e) { this.shadow = 'right-shadow'; }, scrollRight: function (e) { this.shadow = 'left-shadow'; } }; } 

然后在Mobile和Traffic中分別引用當前Mixin即可讓兩個組件同時擁有該功能,參考代碼如下:

<template> .... <scroll-view scroll-x class="{{shadow}}" bindscrolltoupper="scrollLeft" bindscrolltolower="scrollRight" bindscroll="scroll"> <block wx:for-items="{{list}}"> <view class="goods mobile" bindtap="submit({{item.id}}, {{item.amount}}, {{item.type}})"> {{item.price}} </view> </block> </scroll-view> .... </template> <script> import wepy from 'wepy'; import ScrollMixin from '../mixin/scroll'; export default class Mobile extends wepy.component { mixins = [ScrollMixin]; ... } </script> 

登錄態維護

小程序提供 wx.login 接口可以方便的獲取到用戶的 code,通過 code 置換出 session 作為應用態。session 可以儲存在 storage 中或者是內存當中,詳情可參照官方文檔

參照官方文檔整理出我們小程序獲取登錄態的步驟以及應當具備的能力:

  1. 服務器提供一個使用 code 轉換登錄態 session 的接口。

  2. 進入應用時,調用 wx.login() 獲取 code。

  3. 調用接口將 code 轉換為 session,並且儲存到內存或者storage中。

  4. 發請 request 請求時自動帶上 session 字段。

  5. 因為某些原因導致 session 失效時,可以自動再次獲取新的 session 並且發送請求。

畫出流程圖如下:

實現代碼如下:

創建公用模塊 common/global.js 用於存儲全局變量。

export default { session: '' } 

在應用啟動時登錄,並且置換 session,並且利用 wepyjs 的 intercept 功能讓每個 request 都帶上 session。

import wepy from 'wepy'; import api from './common/api'; import G from './common/global'; import 'babel-polyfill'; export default class extends wepy.app { onLaunch() { wepy.login() .then(res => api.getSession(res.code)) .then(res => { G.session = res.session; this.intercept('request', { // request 的攔截器,在每次發送request請求時都會加上session config (p) { p.session = G.session; return p; } }); }); } } 

定義 api 模塊,封裝 request 方法,使其在 session 失效時能再次更新 session 並且發送請求。

// common/api.js import wepy from 'wepy'; import G from './global'; export default { /** * code 置換登錄態 session 接口 */ getSession (code) { return wepy.request({ url: 'https://yourserver/session', data: { code: code } }); }, /** * 封裝 request 方法,在第一次登陸態失效后自動登錄並轉換 session 后重發請求 */ request (data, tryagain) { return new Promise ((resolve, reject) => { wepy.request(data).then(res = > { if (res.data.retCode === 'xxxxx') { // 登錄態驗證失敗 if (tryagain) { reject('Something is wrong'); // code 置換 session 后依然返回登錄態驗證失敗 return; } return wepy.login() // 可能是session過期等原因,獲取最新 code .then(loginRes => this.getSession(loginRes.code)) // 使用最新code置換 session .then(sessionData => { G.session = sessionData.session; return this.request(data, true); // 重發請求 }).catch(reject); } else { resolve(res); } }).catch(reject);; }); }, getMobileList () { let data = {url: 'https://yourserver/api'}; return this.request(data); } }; 

因此,在開發時,就不用去關心何時應該登錄的問題,直接調用接口既可。比如在 mobile.wpy 中獲取列表並渲染:

export default class Mobile extends wepy.app { async onLoad () { this.list = await api.getMobileList(); } } 

上面解釋的是原始的登錄態維護的一種方式,在手機充值小程序里,每個后端接口都有封裝 code 置換 session 的能力,后端接口會優先判斷請求中是否有 session,如果有 session 優先使用 session,如果沒有,使用請求參數中的 code 去置換 session,然后處理請求,再將 session 返回到 response 當中。因此前端流程有些許改變,如下圖:

common/api.js 文件改動如下:

import wepy from 'wepy'; import G from './global'; export default { request (data, tryagain) { return new Promise((resolve, reject) => { if (G.session) { wepy.request(data).then(res => { if (res.data.retCode === 'xxxxx') { // 登錄態驗證失敗 if (tryagain) { reject('Something is wrong'); // code 置換 session 后依然返回登錄態驗證失敗 return; } G.session = ''; return this.request(data, true); } else { resolve(res); } }).catch(reject); } else { wepy.login() // 可能是session過期等原因,獲取最新 code .then(loginRes => { data.data.code = loginRes.code; return wepy.request(data); // 使用 code 發送 request 請求 }) .then(res => { G.session = res.session; // 返回結果中 設置 session resolve(res); }).catch(reject); } }); } }; 

第三方組件

小程序中並不能像H5一樣直接使用alert彈出消息提示,因此可以選擇使用 wx.showToast 的API進行消息提示,但是官方只支持success 和 loading 兩種樣式。重新寫一個 toast 組件成本略高,因此考慮直接使用現成的 wepy-com-toast 組件。使用方法如下:

1 . 安裝組件

npm install wepy-com-toast --save 

2 .無緩存編譯

wepy build --no-cache 

3 .需要的組件中引入 toast 組件

<template> <toast /> </template> <script> import wepy from 'wepy'; import Toast from 'wepy-com-toast'; export default class Index extends wepy.page { components = { toast: Toast }; } </script> 

4 .調用

this.$invoke('toast', 'show', { title: '系統繁忙', img: 'https://yourpicture.com/sad.png', }); 

實現效果如下圖:

數據上報

[MTA是騰訊自家的數據分析平台,在小程序發布后MTA平台很快的就支持了小程序的數據上報。因此手機充值選擇MTA做為數據上報平台,具體步驟如下:

1 .在MTA官網注冊應用。

2 .在mp平台,小程序開發設置中,將https://pingtas.qq.com 添加為可信域名。

3 .安裝 mta-analysis 模塊:npm install mta-analysis --save

4 .在 app.wpy 中添加初始化代碼。

import wepy from 'wepy'; import mta from 'mta-analysis'; export default class extends wepy.app { onLaunch() { mta.App.init({ "appID":"xxxx", // 注冊后得到的appID "eventID":"xxxx", // 注冊后得到的eventID "statPullDownFresh":true, // 使用分析-下來刷新次數/人數,必須先開通自定義事件,並配置了合法的eventID "statShareApp":true, // 使用分析-分享次數/人數,必須先開通自定義事件,並配置了合法的eventID "statReachBottom":true // 使用分析-頁面觸底次數/人數,必須先開通自定義事件,並配置了合法的eventID }); }; } 

這樣就完成了MTA的初始化工作,在每個頁面的 onLoad 事件中加入 init 事件完成頁面的上報。

export default class Index extends wepy.page { onLoad () { mta.Page.init(); }; } 

在 app.wpy 中加入報錯上報。

export default class extends wepy.app { onError () { mta.Event.stat("error",{}); }; } 

以及在其它業務邏輯代碼上加入一些自定義事件上報,比如下單上報,支持上報等等。

mta.Event.stat("payed",{}); 

結束語

至此,基本介紹完了 wepyjs 在手機充值項目的應用了,剩下的就是業務代碼的開發了。wepyjs 通過不停的版本更新迭代去吸收一些傳統框架優秀特性融入其中,比如:組件通訊、props傳值、Mixin、Slot、攔截器等等。也希望在以后能有更多的小程序開發者使用 wepyjs 進行開發。

此文已由作者授權騰訊雲技術社區發布,轉載請注明文章出處


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM