关于微信小程序开发一直想写一篇相关的文章总结和记录下,结果拖延症犯了迟迟没有下笔;这不最近天气不错,于是找一个空闲的下午将这篇文章输出下(好像跟天气没啥关系),那我们就开始吧!

注意:本文默认开发者对微信小程序开发有一定语法基础。小程序开发文档

微信小程序小结

  在接触的微信小程序开发过程中,不难发现微信小程序为了方便开发人员入手对很多底层api进行了很好的封装,比如针对接口请求的wx.request(),针对路由跳转和页面导航的wx.switchTab、wx.navigateTo···等。虽然在一定程度上简化了开发,但是对于项目工程的系统化构建还是不够的,因此本人在对比以前基于Vue开发项目的经验和自身的开发习惯,总结出如下3点可供参考:

  • 1、全局变量和配置信息统一管理;

  • 2、封装路由守卫相关api:vue-routerrouter.beforeEach()router.afterEach()真的香;

  • 3、接口请求公共信息进一步提取封装;

  • 4、封装接口的请求和响应拦截api:axiosaxios.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.requestPromise封装;
      • xxx.js:对应模块的接口管理文件;
    • requestFilter.js:接口请求和响应拦截封装文件;
  • 其他都是初始化默认文件;

二、路由跳转和路由守卫封装

1、路由跳转封装

  微信小程序官方文档为开发者提供了5种路由跳转的api,每一种都有其特殊的用法:

  根据其用法,我们对路由api进行如下封装:微信小程序路由跳转最后对应push、replace、pop、relaunch、switchTabroutes对应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封装

  对于同一个项目而言,微信小程序apiwx.request()中很多参数都是相同的,如果直接使用,需要将这些重复参数一遍又一遍的copy,虽然copy很简单,但是当有一个参数改变了需要找到所有接口一个一个修改,维护起来费劲,再者看着也难受呀;

  借鉴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";

// 获取用户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)
})
}
})

四、接口的请求和响应拦截封装

  axiosaxios.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.jsglobalData属性中,当数据太多或者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.js
App({
//监听小程序初始化
onLaunch(options) {
//获取小程序初始进入的页面信息
let launchInfos = wx.getLaunchOptionsSync()
//将当前页面路由存入全局的数据管理中
this.globalData.currentPage = launchInfos.path
},
···
//全局数据存储
globalData: globalData
})

使用

在页面代码逻辑中可以通过app.globalData.hostwx.$KEYS.TOKEN方式进行调用;

六、总结

  上述关于微信小程序开发的几个方面都是在实践中学习和总结的,技术层面的实现其实很容易,但是个人觉得开发规范项目工程构建才是一个项目的重要基础;完善的规范能够有效的提高开发效率和开发者之间非必要的扯皮!合理的项目工程构建能够优化开发逻辑,提高代码逻辑易读性,减少后期项目的管理时间,同时给予项目更大的扩展性。

  有需要源码的可以关注微信公众号 哇喔WEB 回复 "wxmp"获取;

  欢迎大家讨论留言、进行补充!

让微信小程序开发如鱼得水的更多相关文章

  1. 微信小程序开发心得

    微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...

  2. 【微信小程序开发•系列文章六】生命周期和路由

    这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...

  3. 微信小程序开发日记——高仿知乎日报(下)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  4. 微信小程序开发日记——高仿知乎日报(中)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该教 ...

  5. 微信小程序开发日记——高仿知乎日报(上)

    本人对知乎日报是情有独钟,看我的博客和github就知道了,写了几个不同技术类型的知乎日报APP 要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该 ...

  6. 微信小程序开发工具测评

    1月9日微信小程序正式上线.很多企业都希望能在这个.但是在技术开发的问题上,却不知道该如何下手.经过一些程序员不辞辛苦连夜测试,终于从十余款工具呕心沥血筛选出四款比较靠谱实用的微信小程序开发工具.接下 ...

  7. 微信小程序开发工具的数据,配置,日志等目录在哪儿? 怎么找?

    原文地址:http://www.wxapp-union.com/portal.php?mod=view&aid=359 本文由本站halfyawn原创:感谢原创者:如有疑问,请在评论内回复   ...

  8. 微信小程序开发工具使用与设计规范(二)

    [未经作者本人同意,请勿以任何形式转载] 上一篇文章主要分析了微信小程序应用场景和优劣势.本篇你可以学习到: 如何使用小程序开发工具写一个Hello World 微信小程序设计规范 微信小程序项目结构 ...

  9. 微信小程序开发视频教程新鲜出炉

    微信小程序开发公测了,可是对于新手来说,不同的框架不同的开发机制,如何快速适应呢?微信小程序开发视频教程新鲜出炉了,从零开始一步一步搭建微信小程序,每个章节都会涉及到不同的知识点,等教程学习完你不但掌 ...

随机推荐

  1. js原生方法promise的实现

    一会儿就要回家过年了,再来手写一个promise吧,要不等着下班真的煎熬... <!DOCTYPE html> <html lang="en"> <h ...

  2. java性能问题排查提效脚本工具

    在性能测试过程中,往往会出现各种各样的性能瓶颈.其中java常见瓶颈故障模型有cpu资源瓶颈:文件IO瓶颈:网络IO瓶颈:内存资源瓶颈:资源消耗不高程序本身执行慢等场景模型. 如何快速定位分析这些类型 ...

  3. 算法——模拟LRU机制

    运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制 . 实现 LRUCache 类: LRUCache(int capacity) 以正整数作为容量 capacity 初始化 ...

  4. 《图解TCP/IP》笔记

    OSI参考模型 协议分层 为什么需要分层? 简化网络协议. 每一层只需要衔接上下层的服务. 利于模块化开发. 解耦. 分层的问题 过分模块化.提高数据处理的开销. OSI参考模型 作用及意义 将复杂的 ...

  5. 深入分析 Java、Kotlin、Go 的线程和协程

    前言 协程是什么 协程的好处 进程 进程是什么 进程组成 进程特征 线程 线程是什么 线程组成 任务调度 进程与线程的区别 线程的实现模型 一对一模型 多对一模型 多对多模型 线程的"并发& ...

  6. 【GIT】随笔

    GIT下载地址:https://git-scm.com/download/win安装方法:下一步默认路径:C:\Program Files\Git 使用方法:右键桌面->git bash her ...

  7. MySQL01-数据库概述

    1.概述 1.1 什么是数据库? 用于存储和管理数据的仓库. 1.2 数据库的特点: 1. 持久化存储数据的.其实数据库就是一个文件系统 2. 方便存储和管理数据 3. 使用了统一的方式操作数据库 - ...

  8. Flink读写Redis(三)-读取redis数据

    自定义flink的RedisSource,实现从redis中读取数据,这里借鉴了flink-connector-redis_2.11的实现逻辑,实现对redis读取的逻辑封装,flink-connec ...

  9. js下 Day02、DOM文档对象模型

    一.DOM简介 Document Object Model 文档对象模型 DOM包含了所有HTML元素的属性和方法,以及访问他们的方式: #二.DOM节点 #1. 什么是节点? HTML中所有的元素都 ...

  10. [日常摸鱼]luogu1613跑路

    新年A的第一道题2333 https://www.luogu.org/problemnew/show/P1613 题意:给一张有向图,每条边长为1,每个单位时间只能走$2^k$的长度,$k$可以任意选 ...