WePY 在手机充值小程序中的应用与实践

wepyjs 发布了两个月了,中间经历了不少版本更新,也慢慢开始有一些用户选择 wepyjs 做为开发框架来开发小程序,好比一些线上小程序。javascript

以及一些来自网上的 wepyjs 的相关资源:php

demo源码: one图书管理系统html

组件:图表控件前端

所以我也将手机充值小程序在开发过程当中 wepyjs 的应用心得分享出来,能够参照对比与传统小程序开发上的差别。java

说明:本文不涉及到 wepyjs 的使用与说明,若是须要请参看个人另外一篇文章 ”打造小程序组件化开发框架” 或直接参看wepyjs 项目地址npm

组件化

开发时指望逻辑代码按照业务模块划分,从视觉图上来看,首页能够分为五个模块,分别是:小程序

  • 输入框:Input后端

  • 下拉历史记录:Historyapi

  • 充话费: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 进行开发。

此文已由做者受权腾讯云技术社区发布,转载请注明文章出处

相关文章
相关标签/搜索