目前项目用到的小程序项目架构,比较特殊的是store和behaviors,有个清晰的目录架构可以加快开发的效率,便于维护
behavior
存放小程序需要用到的混合文件,类似vue的mixin
// page-a.js
// var myBehavior = require('./my-behavior.js')
// Page({
// behaviors: [myBehavior],
// onLoad: function() {
// this.data.sharedText === 'This is a piece of data shared between pages.'
// }
// })
const app = getApp()
module.exports = Behavior({
data: {
userInfo: null,
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo')
},
methods: {
// 1.通过button来授权获取 用户信息
getUserInfo: function(e) {
console.log('--getUserInfo--')
app.globalData.userInfo = e.detail.userInfo
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
// 2.通过静默授权的方式来获取 用户信息(为了兼容旧版本)
silentGetUserInfo: function() {
return new Promise((resolve, reject) => {
console.log('--silentGetUserInfo--', app.globalData.userInfo)
if (app.globalData.userInfo) {
this.setData({
userInfo: app.globalData.userInfo,
hasUserInfo: true
})
// 已登录
resolve(app.globalData.userInfo)
} else if (this.data.canIUse) {
// 获取用户信息 ( 如果授权过以后直接获取用户信息 )
wx.getSetting({
success: res => {
console.log('scope.userInfo=', res.authSetting['scope.userInfo'])
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
app.globalData.userInfo = res.userInfo
console.log('res.userInfo', res.userInfo)
// 已登录
resolve(res.userInfo)
},
fail: () => {
// 没登录
reject(null)
}
})
} else {
// 没登录
reject(null)
}
},
fail: () => {
// 没登录
reject(null)
}
})
} else {
// 在没有 open-type=getUserInfo 版本的兼容处理
wx.getUserInfo({
success: res => {
app.globalData.userInfo = res.userInfo
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
// 已登录
resolve(res.userInfo)
},
fail: () => {
// 没登录
reject(null)
}
})
}
})
},
// 3.退出登录
loginOut() {
// 清除page的登录的数据
this.setData({
userInfo: null,
hasUserInfo: false,
isLogin: false
})
// 清除app的登录数据
app.globalData.userInfo = null
}
}
})
config
用于定义环境与接口地址,方便切换与维护
// config.dev.js
// 开发环境
module.exports = {
isDebug: true,
baseUrl: 'http://192.168.1.120',
storageUrl: 'http://192.168.1.120'
}
// index.js
// 1.开发环境
// const conf = require('./config.dev.js')
// 1.测试环境
const conf = require('./config.pro.js')
// 1.正式环境
// const conf = require('./config.real.js')
module.exports = {
isDebug: conf.isDebug,
baseUrl: conf.baseUrl,
storageUrl: conf.storageUrl
}
service
用于存放接口地址
var http = require('../../utils/http.js')
const api_report = {
foo: '/aaa,
boo: '/bbb'
}
const reportList = (payload) => {
return http.post(api_report.foo, payload) // 返回的是 promise
}
const reportSubmit = (payload) => {
return http.post(api_report.boo, payload) // 返回的是 promise
}
// 对外暴露
module.exports = {
reportList,
reportSubmit
}
store
类似vue的vuex作用,用于存储全局变量
// store.js
import { observable, action } from 'mobx-miniprogram'
export const store = observable({
// 数据字段( 相当于data的fields )
numA: 1,
numB: 2,
// 计算属性( 相当于data的fields )
get sum() {
return this.numA + this.numB
},
// actions
update: action(function() {
const sum = this.sum
this.numA = this.numB
this.numB = sum
})
})
util
网络方面:需要注意的是小程序的登录功能因为需要存储token和用户信息,而用户信息是存在小程序的Storage中,在http中会处理到用户的信息
utils.js
// rpx 转换为 px
const rpxTopx =(rpx)=>{
let deviceWidth = wx.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
let px = (deviceWidth/750)*Number(rpx);
return px;
}
// px 转换为 rpx ,传参类型是数字(Number)
const pxTorpx = (px) => {
let deviceWidth = wx.getSystemInfoSync().windowWidth; //获取设备屏幕宽度
let rpx = (750 / Number(px)) * deviceWidth;
return rpx;
}
const getAuthToken = () => {
return wx.getStorageSync('session_key')
}
// 清除登录的数据(退出登录)
const loginOut = () => {
setAuthToken(null)
}
module.exports = {
rpxTopx,
pxTorpx,
getAuthToken,
loginOut
}
http.js
// const baseUrl = '' // 基本路径
const config = require('../config/index')
const utils = require('../utils/util.js')
// 请求方法
function request(url, method, data, header, hasLoading = true) {
data = data || {}
header = header || {}
// // 判断 是否有登录 token
const auth_token = utils.getAuthToken() // 同步
// 对接时候写死token
if (auth_token) {
header['auth_token'] = auth_token
} else {
// 测试 auth_token
header['auth_token'] = 'abc'
}
// 加载动画
if (hasLoading) {
wx.showLoading({
title: '加载中'
})
}
// 创建 promise 对象
const promise = new Promise((resolve, reject) => {
wx.request({
url: config.baseUrl + url, // 地址
header: header,
data: data,
method: method,
success: function(res) {
console.log( res)
if (hasLoading) {
wx.hideLoading() // 隐藏加载动画
}
// 判断是否成功(res的数据需要看接口返回的数据做判断)
if (typeof res.data === 'object') {
// console.log(res)
if (res.data.code === -1 || res.data.code === '1001') {
// 判断是否有登录 请求未登录
// {code: -1
// data: "401"
// msg: "未登录"}
if (res.data.data === '401') {
// 清除登录数据,重新登录
utils.loginOut()
setTimeout(() => {
// 跳转到登录页面
wx.redirectTo({
url: '/pages/mine/mine' // 跳转登录页
})
}, 500)
wx.showToast({
title: '请重新登录!',
icon: 'none',
duration: 2000
})
reject(res)
// 请求失败
} else {
wx.showToast({
title: res.data.msg || '请求失败',
icon: 'none',
duration: 2000
})
reject(res)
}
} else if (res.data.code === 200 || res.data.code === 0) {
resolve(res)
} else {
reject(res)
}
} else {
reject(res)
}
},
// 接口调用失败的回调函数
fail: function(res) {
console.log('x=', config.baseUrl + url)
if (hasLoading) {
wx.hideLoading()
}
wx.showToast({
title: '网络错误!',
icon: 'none',
duration: 2000
})
reject(res)
}
})
})
return promise
}
// 对外暴露
module.exports = {
get: function(url, data, header) {
return request(url, 'GET', data, header)
},
post: function(url, data, header) {
return request(url, 'POST', data, header)
}
}
template
小程序提供模板功能,可自定义几个"暂无数据"的模板进行复用
// 使用模板
<import src="../../templates/no-data/no-data.wxml"/>
<!-- 没有数据 -->
<view
class="report-list-page no-data"
wx:if="{{dataList.length === 0}}">
<template is="noData"></template>
</view>
// 定义模板
<!--templates/no-login/no-data.wxml-->
<template name="noData">
<view style="text-align: center;">
<image
src="../../images/mine/no-find-bg.png"
style="width:506rpx;height:239rpx;margin-top:107rpx"
>
</image>
<view style="color:#8E919C;font-size:28rpx">暂无数据</view>
</view>
</template>
其它
小程序有个坑点需要注意,就是css中background-image引用图片时会无法显示,需要把图片转为base64,这个转换可以在onload生命周期上进行
data:{
bannerBg:'../../images/banner.png'
},
onLoad: function(options) {
const bannerBg = wx.getFileSystemManager().readFileSync(this.data.bannerBg, 'base64')
that.setData({
'bannerBg': 'data:image/jpg;base64,' + bannerBg,
})
},