关于微信小程序开发一直想写一篇相关的文章总结和记录下,结果拖延症犯了迟迟没有下笔;这不最近天气不错,因而找一个空闲的下午将这篇文章输出下(好像跟天气没啥关系)!javascript
注意:本文默认开发者对微信小程序开发有必定语法基础。vue
在接触的微信小程序开发过程当中,不难发现微信小程序为了方便开发人员入手对不少底层api进行了很好的封装,好比针对接口请求的wx.request()
,针对路由跳转和页面导航的wx.switchTab、wx.navigateTo···
等。虽然在必定程度上简化了开发,可是对于项目工程的系统化构建仍是不够的,所以本人在对比之前基于Vue开发项目的经验和自身的开发习惯,总结出以下3点可供参考:java
一、全局变量和配置信息统一管理;ios
vue-router
的router.beforeEach()
和router.afterEach()
真的香;axios
的axios.interceptors.request.use()
和axios.interceptors.response.use()
用过的都说好;从上述四点出发,对微信小程序初始化工程进行规范优化,可以很大程度提升开发效率和进行项目维护管理。封装的好处不仅体如今调用的方便上,也体如今管理的方便上,同时,公共操做集中处理,很大程度减小繁杂重复代码。vue-router
新建微信小程序项目,在项目下新建以下目录和文件:vuex
错误码
匹配列表文件;全局变量
统一管理文件(至关于vuex);5种路由导航
api的封装;拦截
封装;wx.request
的Promise
封装;请求和响应拦截
封装文件;微信小程序官方文档为开发者提供了5种路由跳转的api,每一种都有其特殊的用法:axios
根据其用法,咱们对路由api进行以下封装:微信小程序路由跳转最后对应push、replace、pop、relaunch、switchTab
;routes
对应routeConfig.js中路由路径的配置;routerFilter
对应routerFilter.js文件,对路由跳转以前的逻辑进行处理;小程序
export const routes = { INDEX: "/pages/index/index", TEST: "/pages/test/test", } export default {...routes};
export default () => { ··· //路由跳转前逻辑处理 }
import routes from "../router/routerConfig"; import routerFilter from "./routerFilter" /** * 对wx.navigateTo的封装 * @param {路由} path * @param {参数} params * @param {事件} events */ const push = (path, params, events) => { routerFilter() wx.navigateTo({ url: routes[path] + `?query=${JSON.stringify(params)}`, events: events, success(res) { console.log(res); }, fail(err) { console.log(err); } }) } /** * 对wx.redirectTo的封装 * @param {路由} path * @param {参数} params */ const replace = (path, params) => { routerFilter() wx.redirectTo({ url: routes[path] + `?query=${JSON.stringify(params)}`, success(res) { console.log(res); }, fail(err) { console.log(err); } }) } /** * 对wx.navigateBack的封装 * @param {返回的层级} number */ const pop = (number) => { routerFilter() wx.navigateBack({ delta: number, success(res) { console.log(res); }, fail(err) { console.log(err); } }) } /** * 对wx.reLaunch的封装 * @param {路由} path * @param {参数} params */ const relaunch = (path, params) => { routerFilter() wx.reLaunch({ url: routes[path] + `?query=${JSON.stringify(params)}`, success(res) { console.log(res); }, fail(err) { console.log(err); } }) } /** * 对tabbar的封装 * @param {路由} path */ const switchTab = (path) => { routerFilter() wx.switchTab({ url: routes[path], success(res) { console.log(res); }, fail(err) { console.log(err); } }) } module.exports = { push, replace, pop, relaunch, switchTab }
在app.js
中对封装的路由api进行全局注册:后端
import router from "./router/router.js" //全局注册 wx.router = router
在页面逻辑中使用:微信小程序
//index页面跳转test页面 gotoTest(){ wx.router.push("TEST") }
对于同一个项目而言,微信小程序apiwx.request()
中不少参数都是相同的,若是直接使用,须要将这些重复参数一遍又一遍的copy,虽然copy很简单,可是当有一个参数改变了须要找到全部接口一个一个修改,维护起来费劲,再者看着也难受呀;
借鉴axios
对请求的封装,将wx.request()
封装为Promise
形式岂不美哉:
import formatError from "../requestFilter" const app = getApp() /** * 接口请求封装 * @param {请求方式} method * @param {请求的url} url * @param {请求传递的数据} data */ const request = (method, url, data) => { //设置请求头 const header = { ··· } //promise封装一层,使得调用的时候直接用then和catch接收 return new Promise((resolve, reject) => { wx.request({ method: method, url: app.globalData.host + url, //完整的host data: data, header: header, success(res) { //对成功返回的请求进行数据管理和统一逻辑操做 ··· resolve(res.data) }, fail(err) { wx.showToast({ title: '网络异常,稍后再试!', mask: true, icon: 'none', duration: 3000 }) } }) }) } export default request;
以user.js为例:
import request from "./request"; // 获取用户openid export const usrInfos = data => request("POST", "/user/usrInfos", data);
index页面调用:
//index.js //获取应用实例 const app = getApp() import { usrInfos } from "../../servers/apis/user" Page({ onLoad: function () { //获取用户信息 usrInfos({ uid: "xxxx" }) .then(res => { console.log(res) }) .catch(err => { console.log(err) }) } })
axios
的axios.interceptors.request.use()
和axios.interceptors.response.use()
分别对应接口请求前的拦截处理和数据响应后的拦截处理;根据这个原理咱们对微信小程序的响应也作拦截封装,对接口请求返回错误进行统一管理输出:
import formatError from "../requestFilter" const app = getApp() ··· const request = (method, url, data) => { ··· return new Promise((resolve, reject) => { wx.request({ ··· success(res) { //对成功返回的请求进行数据管理和统一逻辑操做 if(res.statusCode === 200){ //请求返回成功 if(res.data && res.data.code === "SUCCESS"){ //后端对接口请求处理成功,返回数据给接口调用处 resolve(res.data) //then接收 }else{ //后端对也请求判断后认为不合逻辑报错 formatError(res) //统一的报错处理逻辑 reject(res.data) //catch接收 } }else{ reject(res.data) //catch接收 } }, fail(err) { //请求不通报错 wx.showToast({ title: '网络异常,稍后再试!', mask: true, icon: 'none', duration: 3000 }) } }) }) } export default request;
requestFilter.js中能够作不少对报错的处理,这里用一个简单的toast处理示范下:
/** * 对接口返回的后端错误进行格式转化 * @param {接口成功返回的数据} res */ const formatError = (err =>{ wx.showToast({ title: err.message, mask: false, icon: 'none', duration: 3000 }) } export default formatError;
对报错进行统一处理须要明确数据规:
对于数据的管理在小项目的开发中显得不那么重要,可是随着项目愈来愈大,数据愈来愈多,一个很好的数据管理方案可以有效地避免不少bug,这也是vuex可以在vue生态中占有一席之地的缘由。秉承着合理管理数据的原则,对于该封装的数据坚定封装,对于该分模块管理的配置坚定分块管理:
微信小程序中全局的数据管理放在app.js
的globalData
属性中,当数据太多或者app.js逻辑太复杂时,将全局数据提取出来单独管理的确是个好方案:
export default { ··· host: "http://www.wawow.xyz/api/test", //接口请求的域名和接口前缀 hasConfirm: "" //是否已经有了confirm实例 currentPage: "" ··· }
keys.js属于我的开发中的习惯操做,将项目中可能用到的一些常量名称在此集中管理起来,十分方便调用和修改维护:
export default { ··· TOKEN: "token", STORAGEITEM: "test" ··· }
引入app.js:
import router from "./router/router.js" import keys from "./config/keys" import globalData from "./config/globalData" //全局注册 wx.router = router wx.$KEYS = keys //app.js App({ //监听小程序初始化 onLaunch(options) { //获取小程序初始进入的页面信息 let launchInfos = wx.getLaunchOptionsSync() //将当前页面路由存入全局的数据管理中 this.globalData.currentPage = launchInfos.path }, ··· //全局数据存储 globalData: globalData })
在页面代码逻辑中能够经过app.globalData.host
,wx.$KEYS.TOKEN
方式进行调用;
上述关于微信小程序开发的几个方面都是在实践中学习和总结的,技术层面的实现其实很容易,可是我的以为开发规范项目工程构建才是一个项目的重要基础;完善的规范可以有效的提升开发效率和开发者之间非必要的扯皮
!合理的项目工程构建可以优化开发逻辑,提升代码逻辑易读性,减小后期项目的管理时间,同时给予项目更大的扩展性。
欢迎你们讨论留言、进行补充!