参考链接:
(1)
详解微信小程序网络请求接口封装
https://blog.csdn.net/zyplll/article/details/112272324
(2)
微信小程序 wx.request 的封装
https://www.wxapp-union.com/portal.php?mod=view&aid=3660
(3)
微信小程序wx.request的简单封装,超详细
https://blog.csdn.net/qq_43677737/article/details/107769366
(4)
微信小程序接口数据封装 (附前端面试题)
https://blog.csdn.net/weixin_45616142/article/details/107888591
(5)
微信小程序 数据封装,参数传值等经验分享
https://www.jb51.net/article/102471.htm
为实现定制要求和方便调用,对微信小程序的网络请求接口进行了封装
在根目录新建api文件夹并新建httpRequest.js与config.js文件
wx.request(Object)原型
wx.request({
url: 'http://localhost:4000/top/playlist/highquality',//请求的接口地址
method:"get|post|其他",//http请求数据的方式,默认是get
data:{name:'',id:''},//请求的参数,如name和id
header:{//请求头设置,根据需要自己设置
//content-type默认为application/json
'content-type':"application/x-www-form-urlencoded"
},
success(res){//请求成功时的回调函数
console.log(res);
},
fail(msg){
console.log(msg);//请求失败的回调函数
}
})
可能会遇到一个错误。所以,需要在微信开发者工具中设置“不校验合法域名”。
封装API接口的原因
因为本身就是一出现是一大段,自然如果不封包起来通过调用的方式进行整理的话,直接放到网站源码中,自然就会加大的源码的体积,而且还会影响到代码的美现。而且现在很多的杀来毒软件都把JS代码误报为病毒,况源且JS代码外露也很容易让不良分子找到攻击网站的参照物。
API接口封装的好处
- 提高网站的打开速度。
- 符合SEO搜索引擎思路。
- 以便于我们后期的维护,如果当我们的接口发生更改的时候,我们修改也很方便,不需要再一个页面的查找。
- 所以,对于提高网站访问zhidao速度,最好把JS代码封包起来,而且还要通过ROBOT文件把之屏蔽掉,毕竟这些都是搜索引挚不能识别的,外放对于提高收录只有坏外没有好处。
- 所以,为了收录、为了访问速度能封装的JS代码就尽量封装。
一、例子1
- 设置请求域名
// 设置请求域名
let ENV = __wxConfig.envVersion
let httpUrl = '',
if (ENV == 'develop') {
// 测试版开发环境域名
httpUrl = 'https://*******.com/api';
} else if (ENV == 'trial') {
// // 体验版环境域名
httpUrl = 'http://*******.com/api';
} else if (ENV == 'release') {
// 线上环境域名
httpUrl = 'https://*******.com/api';
}
export default httpUrl
-
在utils下方建立一个qs文件
根据自己项目数据需求是否下载qs(网址:
https://gitee.com/zyplll/qs-file
) -
封装httpRequest
import Qs from '../utils/qs'
import httpUrl from './config'
const apiRequest = (option) => {
/*
option.url:请求地址
option.header:头信息
option.params:参数
*/
let promise = new Promise(function (resolve, reject) {
wx.showLoading({
title: '努力加载中',
mask: true
});
// 设置请求头
let headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
}
// 对数据进行处理转换
let params = Qs.stringify(option.params, {
arrayFormat: 'indices',
allowDots: true
}).replace(/\[\d+\]=/g, "=")
wx.request({
url: httpUrl.connectorUrl + option.url,
data: params,
method: 'post',
header: headers,
// 超时时间
timeout: 60000,
success: function (res) {
wx.hideLoading()
if (res.statusCode == 200) {
res = res.data
if (res.code == -1) {
// 跳转到登录
} else if (res.code == 2) {
wx.showModal({
title: '提示',
content: '您没有访问权限',
success: function () {
// 返回上一页
wx.navigateBack()
if (res.confirm) {
// 点击了确定
} else if (res.cancel) {
// 点击了取消
}
}
})
} else {
// 请求成功
resolve(res)
}
} else if (res.statusCode == 500) {
wx.showToast({
title: '后台异常',
icon: 'none'
})
}
},
fail: function (res) {
wx.hideLoading()
wx.showToast({
title: res.errMsg,
image: '/static/icon/error.png'
})
}
})
})
return promise
}
module.exports = apiRequest;
- 在api文件中统一处理api请求
import httpRequest from './httpRequest'
export const notaryHistoryPage(params) {
return httpRequest({ url: '/api/*******', params }).then(res => res)
},
- 页面使用
var api = require('../../api/api.js').default;
Page({
show:function() {
let params = {
id:1
}
api.notaryHistoryPage(params).then(res=>{}).catch(res=>{})
}
})
二、例子2:使用 Promise 封装 wx.request
我们大部分网站都是用 cookie 来维护登录状态的,但是小程序是无法用 cookie 来维护登录状态的,那么我们先获取请求头的 cookie, 然后将 cookie 保存在全局变量当中(相信获取 cookie 肯定没问题吧, 这部分就不展示了)
// wx.request 封装
var app = getApp()
function wxRequest(url, config, resolve, reject) {
let {
data = {},
contentType = 'application/json',
method = 'GET',
...other
} = {...config}
wx.request({
url: url,
data: {...data},
method: method,
header: {
'content-type': contentType,
'Cookie': app.globalData.cookie // 全局变量中获取 cookie
},
success: (data) => resolve(data),
fail: (err) => reject(err)
})
}
module.exports = {
wxRequest: wxRequest
}
业务对应的配置 js文件
// 用 import 或者 require 引入模块
import util from '../../../util/util.js'
var Promise = require('../../../plugin/promise.js') // 请注意 Promise 要手动引入,内测版是自动引入的
// 获取个人信息
const API_USERINFO = "https://www.***/get"
// 获取剩余金额
const API_BALANCE = 'https://www.***/get'
// 获取昨日消费数据
const API_LASTCOST = 'https://www.***/get'
// 获取个人信息事件
function getUserInfo(data, contentType) {
var promise = new Promise((resolve, reject) => {
util.wxRequest(API_USERINFO, { data, contentType }, resolve, reject)
})
// return promise
return promise.then(res => {
return res.data
}).catch(err => {
console.log(err)
})
}
// 获取剩余金额事件
function getBalance(data, contentType) {
var promise = new Promise((resolve, reject) => {
util.wxRequest(API_BALANCE, { data, contentType }, resolve, reject)
})
// return promise
return promise.then(res => {
return res.data
}).catch(err => {
console.log(err)
})
}
// 获取昨日消费数据
function getLastCost(data, contentType, method) {
var promise = new Promise((resolve, reject) => {
util.wxRequest(API_LASTCOST, { data, contentType, method }, resolve, reject)
})
// return promise
return promise.then(res => {
return res.data
}).catch(err => {
console.log(err)
})
}
module.exports = {
getUserInfo: getUserInfo,
getBalance: getBalance,
getLastCost: getLastCost
}
三、例子3
- http.js
const pubUrl = "http://localhost:3000/api"//这是我要请求的数据接口的公共部分
const http = (options) =>{
return new Promise((resolve,reject) => {
wx.request({
url: pubUrl+options.url,
method:options.method || 'get',
data:options.data || {},
header: options.header || {
'content-type':'application/x-www-form-urlencoded'
},
success:resolve,
fail:reject
})
})
}
export default http
- app.js(这里主要是对要请求的接口进行了封装,接口会有很多,放在同一个文件中方便管理)
import http from 'http.js' //引入上面封装好的请求方法
// 获取商品的一级分类,不需要参数
const _getTopCate = () => {
return http({
url:'/getcate'
})
}
//获取商品详情,需要传入参数
const _getDetail = (id) => {
return http({
url:'/getgoodsinfo',
data:{
id
}
})
}
// 将方法导出,实现复用
export default{
_getTopCate,
_getDetail
}
- 具体需要请求数据的页面的js文件,如:index.js
import Api from '../../utils/api.js' //首先要引入封装好的上述api文件,路径根据自己文件的位置
Page({
data:{
},
// 因为请求数据的方法用promise封装,所以需要配合async 和 await 来获取到promise中的数据
async _getCate(){ //在需要请求接口获取数据的方法中调用api中的方法
let result = await Api._getTopCate();
console.log(result);
},
async _getDetail(){
let result = await Api._getDetail(1);
console.log(result)
}
})
- index.wxml
<view bindtap="_getCate">获取一级分类</view> //点击会触发上述js中的_getCate()事件,然后调用封装的接口获取到数据
<view bindtap="_getDetail">请求数据商品详情</view>
四、例子4
在小程序里面创建一个公共目录http,里面设置公共访问的url、地址环境。
然后在http目录下面创建env.js。
//commonJs预览 --- node.js采用的就是该规范
//什么是common.js规范:每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、
//函数、类,都是私有的,对其他文件不可见。
//这里使用的接口呢都是自己模拟的,亲么可以根据自己的需求进行添加
module.exports={
//开发环境的url
dev:{
baseUrl:"http://localhost:3000"
},
//测试环境url
test:{
baseUrl:"http://www.test.com"
},
//线上环境url
prod:{
baseUrl:'https://api.it120.cc'
}
}
继续在http目录下面创建一个request.js文件来二次封装wx.request。
// 引入env中的url
const { baseUrl } = require('./env.js').prod;
//在这里添加我们的专业域名
const subDomain = 'xxx';
/*
*二次封装wx.request
*
*/
module.exports = {
/**
* 二次封装wx.request
* {String }url:请求的接口地址
* {String} method:请求方式 GET,POST....
* {Object} data:要传递的参数
* { boolean }isSubDomain:表示是否添加二级子域名 true代表添加, false代表不添加
*/
request: (url, method, data, isSubDomain) => {
console.log('这是我封装的ajax请求', baseUrl);
//这里使用ES6的写法拼接的字符串
let _url = `${baseUrl}/${isSubDomain ? subDomain: '' }${url}`;
console.log(_url);
return new Promise((resolve, reject) => {
wx.showLoading({
title: '正在加载',
});
wx.request({
url: _url,
data: data,
method: method,
header: {
'content-type': 'application/x-www-form-urlencoded',
},
success: (res) => {
console.log('从接口获取到的数据', res);
let { code } = res.data;
if(code===0) {
resolve(res.data);
wx.hideLoading();
}else {
wx.showToast({
title: '数据请求错误',
})
}
},
fail() {
reject('接口有误,请检查')
}
});
});
},
}
http目录下面在创建一个api.js文件来封装我们的reuest请求。
//引入封装的reuest请求
const { request } = require('./request.js')
//基于业务封装的接口
module.exports={
/* 轮播图 */
banners:()=>{
return request(','GET',{},true);
},
/* 封装商品列表的方法 */
getGoodsList:()=>{
return request('要请求的路径','请求方式|GET|POST',{要携带的参数},是否添加子域名 |true|false);
},
/* 添加商品收藏 */
addGoodsFav: (goodsId, token)=>{
return request('要请求的路径', 'POST', { goodsId:goodsId, token:token},true);
},
/* 获取商品的分类 */
getGoodsCate:()=>{
return request('要请求的路径','GET',{},true);
}
}
然后再需要的js页面引入就ok了!
const { getGoodsList } = require('../../http/api.js')
//定义一个点击事件来测试我们请求的接口
onbBn() {
// getGoodsList();
// addGoodsFav();
// getGoodsCate()
console.log('这是我们要测试的接口',getGoodsCate());
//请求后抛出
banners().then(res => {
console.log('终于等到你',res);
})
五、例子5
-
在与pages同级目录下新建http文件夹:
- 在http文件夹下新建env.js文件,搭建环境:
module.exports={
//开发环境
dev:{
baseUrl:'http://127.0.0.1:8080'
},
//生产环境
prod:{
baseUrl:'https://api.it120.cc'
},
//测试环境
test:{
baseUrl:'https://api.1909A.com'
}
}
- 在http文件夹下新建request.js文件,进行接口封装的操作:
const { baseUrl } = require('./env.js').prod
const vipUrl = "sbq"
module.exports = {
// request是一个函数,封装了request,其中的参数不填的话就会有默认值
request:function(url,method="GET",data={},isSubDomain=true){
//把正确的请求地址拼接起来
let fullurl = `${baseUrl}/${isSubDomain?vipUrl:""}/${url}`
//Promise 对象用于表示一个异步操作的最终完成 (或失败), 及其结果值.
return new Promise((resolve,reject)=>{
wx.request({
url: fullurl,
method,
data,
header:{
//此处的头部信息要注意接口文档
"content-type":"pplication/x-www-form-urlencoded"
},
//成功回调
success(res){
if(res.statusCode === 200 && res.data.code===0){
//返回的数据
resolve(res.data.data)
}else{
console.log("接口有问题")
}
},
//失败回调
fail(){
console.log("接口问题")
}
})
})
}
}
- 在http文件夹下新建api.js文件,就是项目中用到的各种业务接口的封装(例举商品列表接口):
const {request} = require('./request.js')
module.exports={
// 商品列表接口
goodsItem:()=>{
return request("shop/goods/list","GET","",true)
}
}
- 然后在对应的组件里面直接调用就可以:
// components/xhy_goodItem/xhy_goodItem.js
const { goodsItem }=require('../../http/api.js')
Component({
//组件的生命周期
lifetimes: {
created() {
this.getData();
},
},
/**
* 组件的初始数据
*/
data: {
goodItem: []
},
/**
* 组件的方法列表
*/
methods: {
getData() {
goodsItem().then(res=>{
this.setData({
goodItem:res
})
})
}
}
})
- 拿到数据,正常渲染页面就可以了。