### [让微信小程序开发如鱼得水(实例)](https://www.prosaas.cn/article/16418) **Published:** 2021-04-15T01:46:22 **Author:** 5201314 **Excerpt:** 关于微信小程序开发一直想写一篇相关的文章总结和记录下,结果拖延症犯了迟迟没有下笔;这不最近天气不错,于是找一个… ![](https://img.php.cn/upload/article/000/000/052/6077967f84a55502.jpg)   关于微信小程序开发一直想写一篇相关的文章总结和记录下,结果拖延症犯了迟迟没有下笔;这不最近天气不错,于是找一个空闲的下午将这篇文章输出下(好像跟天气没啥关系),那我们就开始吧! 注意:**本文默认开发者对微信小程序开发有一定语法基础。**小程序开发文档 **相关免费学习推荐:****微信小程序开发** **微信小程序小结**   在接触的微信小程序开发过程中,不难发现微信小程序为了方便开发人员入手对很多底层api进行了很好的封装,比如针对接口请求的`wx.request()`,针对路由跳转和页面导航的`wx.switchTab、wx.navigateTo···`等。虽然在一定程度上简化了开发,但是对于项目工程的系统化构建还是不够的,因此本人在对比以前基于Vue开发项目的经验和自身的开发习惯,总结出如下3点可供参考: - 1、全局变量和配置信息统一管理; - 2、封装路由守卫相关api:`vue-router`的`router.beforeEach()`和`router.afterEach()`真的香; - 3、接口请求公共信息进一步提取封装; - 4、封装接口的请求和响应拦截api:`axios`的`axios.interceptors.request.use()`和`axios.interceptors.response.use()`用过的都说好; 从上述四点出发,对微信小程序初始化工程进行规范优化,能够很大程度提高开发效率和进行项目维护管理。封装的好处不只体现在调用的方便上,也体现在管理的方便上,同时,公共操作集中处理,很大程度减少繁杂重复代码。 **一、项目初始化**    新建微信小程序项目,在项目下新建如下目录和文件: - config文件夹:统一管理可配置的信息和变量; - erroList.js:接口报错`错误码`匹配列表文件; - globalData.js:`全局变量`统一管理文件(相当于vuex); - keys.js:可配置系统信息管理文件(全局常量命名等); - pages文件夹:小程序页面文件管理文件夹(每个页面一个子文件夹目录); - router文件夹:路由管理文件件; - router.js:对微信小程序`5种路由导航`api的封装; - routerConfig.js:页面路由名称和路径匹配配置文件; - routerFilter.js:路由前置`拦截`封装; - servers文件件:接口请求服务管理文件夹; - apis文件夹:request请求封装管理和接口api配置管理文件夹; - request.js:对`wx.request`的`Promise`封装; - xxx.js:对应模块的接口管理文件; - requestFilter.js:接口`请求和响应拦截`封装文件; - 其他都是初始化默认文件; ![](https://img.php.cn/upload/article/000/000/052/89d3a553c3b8b145a4d0619da9927bdb-1.png) **二、路由跳转和路由守卫封装** **1、路由跳转封装**   微信小程序官方文档为开发者提供了5种路由跳转的api,每一种都有其特殊的用法: ![](https://img.php.cn/upload/article/000/000/052/1d2b3509a122750a5cf62e5908d1d4dc-2.png)   根据其用法,我们对路由api进行如下封装:微信小程序路由跳转最后对应`push、replace、pop、relaunch、switchTab`;`routes`对应routeConfig.js中路由路径的配置;`routerFilter`对应routerFilter.js文件,对路由跳转之前的逻辑进行处理; #### routeConfig.js(每次新增页面后需要手动添加): export const routes =    {     INDEX: "/pages/index/index",     TEST: "/pages/test/test",   }export default {...routes}; #### routerFilter.js: export default () => {   ···  //路由跳转前逻辑处理} #### router.js(routerFilter负责路由跳转前公共操作处理,在success和fail中对路由跳转后的公共操作进行处理): 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} **2、全局注册和使用** 在`app.js`中对封装的路由api进行全局注册: import router  from "./router/router.js"//全局注册wx.router = router 在页面逻辑中使用: //index页面跳转test页面 gotoTest(){    wx.router.push("TEST")} **三、接口请求Promise封装**   对于同一个项目而言,微信小程序api`wx.request()`中很多参数都是相同的,如果直接使用,需要将这些重复参数一遍又一遍的copy,虽然copy很简单,但是当有一个参数改变了需要找到所有接口一个一个修改,维护起来费劲,再者看着也难受呀; ![](https://img.php.cn/upload/article/000/000/052/1d2b3509a122750a5cf62e5908d1d4dc-3.png)   借鉴`axios`对请求的封装,将`wx.request()`封装为`Promise`形式岂不美哉: #### request.js: 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";// 获取用户openidexport 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()`分别对应接口请求前的拦截处理和数据响应后的拦截处理;根据这个原理我们对微信小程序的响应也做拦截封装,对接口请求返回错误进行统一管理输出: #### request.js 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 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生态中占有一席之地的原因。秉承着合理管理数据的原则,对于该封装的数据坚决封装,对于该分模块管理的配置坚决分块管理: #### globalData.js 微信小程序中全局的数据管理放在`app.js`的`globalData`属性中,当数据太多或者app.js逻辑太复杂时,将全局数据提取出来单独管理的确是个好方案: export default {   ···   host: "http://www.wawow.xyz/api/test", //接口请求的域名和接口前缀    hasConfirm: "" //是否已经有了confirm实例   currentPage: ""   ···} #### keys.js 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.jsApp({   //监听小程序初始化   onLaunch(options) {     //获取小程序初始进入的页面信息     let launchInfos = wx.getLaunchOptionsSync()     //将当前页面路由存入全局的数据管理中     this.globalData.currentPage = launchInfos.path  },   ···  //全局数据存储   globalData: globalData}) #### 使用 在页面代码逻辑中可以通过`app.globalData.host`,`wx.$KEYS.TOKEN`方式进行调用; **六、总结**   上述关于微信小程序开发的几个方面都是在实践中学习和总结的,技术层面的实现其实很容易,但是个人觉得开发规范项目工程构建才是一个项目的重要基础;完善的规范能够有效的提高开发效率和开发者之间非必要的`扯皮`!合理的项目工程构建能够优化开发逻辑,提高代码逻辑易读性,减少后期项目的管理时间,同时给予项目更大的扩展性。 > **相关学习推荐:****小程序开发教程** 以上就是让微信小程序开发如鱼得水(实例)的详细内容,更多请关注知企PROSAAS其它相关文章! **Categories:** 后端开发 ---