前言
目前随便百度一下都能找到大把的微信小程序接口封装文章,各式各样但都大同小异,那我为什么还要发这篇文章呢,话说懒也是促进人类进步的一种方式,所以我始终想着一劳永逸的写法,最好从建立项目封装接口后就能用到项目下架,这也是我发这篇文章的目的,接下来看正文。
1. 新建 api 目录
在项目内新建 api
目录,在该目录下新建图示中的 4 个目录文件,我们把项目内所有涉及到网络接口封装的方法全写里面。哪怕以后随着项目需求的变更需要更新封装方法或者我们需要更新接口都在该目录内操作即可。
2. api 目录详解
1. modules
* 该目录中存放项目内所有接口文件
* 该目录中的文件层级不限,可按照任意模式划分目录结构,但接口文件名称需统一设为 `*.js`,且接口文件名称不可重复,因为我们将以接口文件名作为接口封装后调用的模块名。
例:可按接口类型划分目录结构
modules
├─ get
│ ├─ a.js
│ ├─ b.js
├─ post
│ ├─ c.js
├─ put
│ ├─ d.js
├─ delete
│ ├─ e.js
例:可按项目模块划分目录结构
modules
├─ access
│ ├─ login.js
│ ├─ logout.js
├─ list.js
2. index.js
该文件主要是获取 modules 目录下的所有接口文件,然后统一对接口文件进行处理后输出供页面调用。
3. modules.js
该文件其实在开发环境下是用不上了,主要是用在生产环境。用于输出所有接口文件。
4. request.js
该文件是对微信小程序原生的网络请求进行封装,方便我们后续使用。
对于接口封装,我们应该考虑到封装之后的适用性和实用性以及兼容性。
封装不是说要去改装他,而应该是对原生请求的一种升级,在兼容微信原生请求的基础上在去进行我们的封装操作,使其更加适用在当前项目。
3. 完善目录
1. request.js
首先我们对微信小程序原生网络请求进行封装,轻度封装即可,不推荐重度封装,封装的越多越难阅读,适用性也越差,当然这个度可根据自己当前项目情况自行斟酌。打开 request.js
文件,写入如下代码:
let baseURL;
const version = wx.getAccountInfoSync().miniProgram.envVersion;
switch (version) {
// 开发版
case 'develop':
//填入自己当前项目的后端接口基础地址
baseURL = 'https://www.baidu.com';
break;
// 体验版
case 'trial':
baseURL = '';
break;
// 正式版
case 'release':
baseURL = '';
break;
default:
break;
};
// 自定义接口请求初始信息,比如接口超时,请求头等,具体参数请参考微信小程序文档
const params = {};
const request = (options) => {
return new Promise((resolve, reject) => {
wx.request({
...params,
...options,
url: baseURL + options.url,
success: (res) => { resolve(res) },
fail: (err) => { reject(err) }
})
})
};
// 按请求方式进行封装
class Request {
get(options) { return request({ method: 'GET', ...options })};
post(options) { return request({ method: 'POST', ...options })};
put(options) { return request({ method: 'PUT', ...options })};
delete(options) { return request({ method: 'DELETE', ...options })};
}
export default new Request();
2. modules
比如当前项目我是按照接口请求方式进行的一个目录划分,里面的 *.js
文件按图示所写就可以,比如图中所示的 list.js
, list
在页面中调用的时候会作为模块名使用,所有在 modules
目录下文件名不可重名。
import request from "@/api/request.js";
module.exports = {
// 新闻列表
newsList(data, options) { return request.get({ url: `/news/list`, data: data, ...options})},
// 用户列表
userList(data, options) {return request.get({url: `/user/list`, data: data, ...options})}
}
因为此处引用使用的是绝对路径,所以我们需要在 app.json 中加上一条属性
"resolveAlias": {
"@/*": "/*"
}
3. index.js
index.js
是对 modules
目录代码如下:
import modules from '@/api/modules';
const api = {};
const list = [];
// 根据当前环境调用不同的 api 加载方式
const version = wx.getAccountInfoSync().miniProgram.envVersion;
if (version == 'develop') {
// 因为在手机调试预览时也是处于 develop 模式,但是手机是获取不到 modules 目录的,此处是判断处于PC端还是手机端
if (wx.getFileSystemManager().readdirSync('/').includes('api')) {
// 递归获取 modules 目录下所有js后缀的文件
const getAllFiles = (path) => {
const files = wx.getFileSystemManager().readdirSync(path);
// 根据后缀判断是否为文件夹
files.map(file => {
const filePath = `${path}/${file}`;
if (file.split(".").pop() != "js") {
// 递归获取子文件夹下的所有文件
getAllFiles(filePath);
} else {
const moduleName = file.split('.')[0];
const modulePath = filePath.replace('/api', '.');
list.push({ moduleName: moduleName, modulePath: modulePath});
console.log(list);
api[moduleName] = require('./' + modulePath);
}
})
}
getAllFiles('/api/modules');
// 判断是否有重名 api
const hasDuplicates = list.length !== new Set(list.map(item => item.moduleName)).size;
if (hasDuplicates) {
const duplicates = list.map(item => item.moduleName).filter((element, index) => list.map(item => item.moduleName).indexOf(element) !== index);
// 此处会输出 modules 目录下重名的js文件名
console.error('api重名,可能造成接口调用错误,请检查后重试\n', duplicates);
};
// 获取 api 列表
// 此处就是 modules.js 内容的来源
// 如 modules 目录下的文件没有变更的时候可注释掉该行打印内容
console.log(JSON.stringify(list, null, 2));
} else {
modules.map(item => {
api[item.moduleName] = require('./' + item.modulePath);
})
}
} else {
modules.map(item => {
api[item.moduleName] = require('./' + item.modulePath);
})
}
export default api;
4. modules.js
这里也是唯一有点麻烦的地方,因为微信小程序的限制不能读取项目目录,所以我们需要手动更新该文件,每当 modules
目录下新增或删除文件后就需要更新 modules.js
以保持接口列表为最新,不然在电脑上调试的时候没有问题,手机设备访问就会报错,另外此处只记录文件名和文件路径,当这两个因素发生变化时就需要更新该文件。
const modules = [
{
"moduleName": "list",
"modulePath": "./modules/get/list.js"
}
];
export default modules;
4. 页面调用
接口封装完成后需要导入到全局变量中,这样我们就不需要每次在页面中调用接口前先要去 import 接口文件,打开 app.js
引入封装好的接口文件,代码如下:
导入完成后在页面中的使用方式如下:
总结
该封装方法仅供参考,大家可根据自己当前的项目情况自行完善使用。
坑是踩不完的,学如逆水行舟,不进则退。如有不完善或错误的地方请大家指正,大家共同进步!