前言
? ? ? ? 在項(xiàng)目開發(fā)過程中,往往需要對請求進(jìn)行二次封裝,這篇文章將對uni.request()進(jìn)行二次封裝,并實(shí)現(xiàn)多個環(huán)境的請求配置,對請求方式,數(shù)據(jù)格式等進(jìn)行封裝,將請求做到最簡化。
一.封裝uni.request()
第一步基于uni.request()進(jìn)行二次封裝,集成項(xiàng)目開發(fā)中需要的參數(shù)及方法。
新建src/request/index.ts文件內(nèi)容如下:?
/**
* 創(chuàng)建request請求
* @returns
*/
const request = <T = any>(
url: string, //接口地址
type: 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT', //請求方式
data: AnyObject, //請求的參數(shù)
header: any //設(shè)置請求的 header
): Promise<T> => {
// 拼接url config.base后面會講到
let apiUrl = config.base + url
// 這里是獲取存在Store中的token,獲取方式根據(jù)自身項(xiàng)目來
const userStore = useUserStore()
// 全局添加請求頭
let obj = {
// 獲取Store中的token || 獲取本地存儲的token
'Authori-zation': (userStore.token || storage.getData("TOKEN") || ""),
}
if (header) {
// 有無傳入header,有則合并
let headers = Object.assign(header, obj);
header = headers;
} else {
header = obj
}
if (data) {
// 清除無用參數(shù)
Object.keys(data).forEach(key => {
if (data[key] == null || data[key] == undefined || data[key] === '') {
delete (data[key]);
}
})
}
return new Promise((resolve, reject) => {
uni.request({
url: apiUrl,
method: type,
data,
header,
success(res) {
if (res.statusCode == 200) {
const data: any = res.data;
if (data.code == 0) {
// 正常拋出數(shù)據(jù)
resolve(data.data as T)
} else {
if(data.code == 401) {
// 未登錄
uni.redirectTo({
url: "" //未登錄跳轉(zhuǎn)指定頁面
})
uni.hideLoading();
return reject(data);
}
// 錯誤數(shù)據(jù)
uni.hideLoading();
// 彈窗錯誤框,這里是自己封裝組件,
common.toastErr(data.message || "網(wǎng)絡(luò)請求異常")
reject(data);
}
} else {
console.log(data)
uni.hideLoading();
common.toastErr("網(wǎng)絡(luò)請求異常")
reject(data)
}
},
fail(err) {
console.log(err)
uni.hideLoading();
common.toastErr("網(wǎng)絡(luò)請求異常")
reject(err)
}
})
})
}
二.根據(jù)環(huán)境配置請求地址
????????上面我們已經(jīng)對uni.request()進(jìn)行了封裝,前面代碼中提到的config.base就是我們需要獲取的地址,在項(xiàng)目開發(fā)過程中,往往會有多個環(huán)境,如開發(fā)環(huán)境、預(yù)生產(chǎn)環(huán)境、生產(chǎn)環(huán)境等等,那我們怎么根據(jù)不同環(huán)境來配置對應(yīng)的請求地址或其他信息呢?
要做到根據(jù)不同環(huán)境讀取不同配置信息,那我們這里就需要用到uni.getAccountInfoSync()方法,該方法可以獲取當(dāng)前小程序賬號信息,其返回值miniProgram屬性的envVersion值,就是我們想獲取的當(dāng)前小程序環(huán)境:
屬性 | 類型 | 說明 |
envVersion | string | 小程序當(dāng)前環(huán)境版本:develop開發(fā)板;trial體驗(yàn)版;release正式版 |
已經(jīng)解決了獲取環(huán)境問題,那我們就可以來配置不同環(huán)境啦,這里分三種環(huán)境:
- dev 開發(fā)環(huán)境
- test 測試環(huán)境
- prod 生產(chǎn)環(huán)境
在src下新建config文件,其下dev,test,prod三個文件夾用來配置對應(yīng)信息。
先對配置進(jìn)行ts規(guī)范,因?yàn)轫?xiàng)目中可能不知請求地址一個配置,可能還有應(yīng)用地圖的key等其他信息,我們可以統(tǒng)一配置,新建config/types.ts? 如下:
export interface IConfig {
// 接口主地址
base: string;
// 環(huán)境模式
mode: string;
// 地圖key
mapKey: string;
// 密鑰
secretKey: string;
}
?接下來就是具體內(nèi)容的配置,新建config/dev/index.ts如下:
// dev 開發(fā)環(huán)境
import {IConfig} from "../types";
const test: IConfig = {
// #ifdef H5
base: "",
// #endif
// #ifdef MP-WEIXIN
base:'http://192.168.1.15:8090/api',
// #endif
// 模式
mode: "dev",
// 地圖key
mapKey: "",
// Secret Key
secretKey: ""
}
export default test;
?新建config/test/index.ts如下:
// test 測試環(huán)境
import {IConfig} from "../types";
const test: IConfig = {
// #ifdef H5
base: "",
// #endif
// #ifdef MP-WEIXIN
base:'http://192.168.1.15:8090/api',
// #endif
// 模式
mode: "test",
// 地圖key
mapKey: "",
// Secret Key
secretKey: ""
}
export default test;
??新建config/prod/index.ts如下:
// prod 生產(chǎn)環(huán)境
import {IConfig} from "../types";
const test: IConfig = {
// #ifdef H5
base: "",
// #endif
// #ifdef MP-WEIXIN
base:'http://www.baidu.com/api',
// #endif
// 模式
mode: "prod",
// 地圖key
mapKey: "",
// Secret Key
secretKey: ""
}
export default test;
上面三個文件中使用了#ifdef?#endif 注釋,這是因?yàn)槲覀兊捻?xiàng)目可能不只是在小程序上運(yùn)行,如我開發(fā)過的項(xiàng)目就有一個溯原H5頁面,那這時(shí)候就得區(qū)分不同平臺,這里簡單介紹一下如何區(qū)分:
?#ifdef?#endif其實(shí)就是條件編譯,條件編譯是用特殊注釋作為標(biāo)記,在編譯時(shí)根據(jù)特殊注釋,將注釋里面的代碼編譯到不同平臺,其寫法如下:
已?#ifdef 或 #ifndef 加??%PLATFORM%? 開頭 ,中間部分寫代碼,以?#endif?結(jié)尾。
- #ifdef :if defined 僅在某平臺存在
- #ifndef:if not defined 除了某平臺均存在
- %PLATFORM%:平臺名稱,如H5,MP-WEIXIN?
所以上面三個文件中條件編譯的意思就是只在微信小程序存在/只在H5頁面存在。
此時(shí)我們已經(jīng)準(zhǔn)備好了三種環(huán)境下的配置,那么接下來就是對當(dāng)前環(huán)境的判斷及使用,在config下新建index.ts 內(nèi)容如下:?
import { IConfig } from "./types";
import prod from "./prod";
import test from "./test";
import dev from "./dev";
let obj: IConfig;
// #ifdef MP-WEIXIN
const plat = uni.getAccountInfoSync().miniProgram.envVersion
if(plat === "release") {
obj = prod
} else if(plat === "trial") {
obj = test
} else {
obj = dev
}
// #endif
// #ifdef H5
if(import.meta.env.MODE === "production") {
obj = prod
} else if(import.meta.env.MODE === "test") {
obj = test
} else {
obj = dev
}
// #endif
export default obj;
這一文件中就用到了上面講的獲取當(dāng)前環(huán)境的方法,來配置對應(yīng)信息,前面在request/index文件中提到的config.base就是來自于此。
三.封裝請求方式
? ? ? ? 到這個位置其實(shí)我們的封裝已經(jīng)可以使用了,但是在實(shí)際開發(fā)中,還分有g(shù)et,post,put,delete等請求方式,及json,form表單等數(shù)據(jù)格式,那為了后續(xù)開發(fā)的便捷,我們還有繼續(xù)根據(jù)請求方式及數(shù)據(jù)格式封裝請求,這一部分就繼續(xù)寫在request/index.ts 文件中:
/**
* http get 請求
* @param url 請求接口
* @param data 請求參數(shù)
* @returns
*/
const get = <T = any>(
url: string,
data: AnyObject
): Promise<T> => {
return request(url, 'GET', data, {})
}
/**
* http post json請求
* @param url 請求接口
* @param data 請求參數(shù)
* @returns
*/
const postJ = <T = any>(
url: string,
data: AnyObject
): Promise<T> => {
return request(url, 'POST', data, {
'Content-Type': 'application/json'
})
}
/**
* http post form表單請求
* @param url 請求接口
* @param data 請求參數(shù)
* @returns
*/
const postW = <T = any>(
url: string,
data: AnyObject
): Promise<T> => {
return request(url, 'POST', data, {
'Content-Type': 'application/x-www-form-urlencoded'
})
}
/**
* http put json請求
* @param url 請求接口
* @param data 請求參數(shù)
* @returns
*/
const putJ = <T = any>(url: string, data: AnyObject): Promise<T> => {
return request(url, 'PUT', data, {
'Content-Type': 'application/json'
})
}
/**
* http put form表單請求
* @param url 請求接口
* @param data 請求參數(shù)
* @returns
*/
const putW = <T = any>(url: string, data: AnyObject): Promise<T> => {
return request(url, 'PUT', data, {
'Content-Type': 'application/x-www-form-urlencoded'
})
}
/**
* http delete請求
* @param url 請求接口
* @param data 請求參數(shù)
* @returns
*/
const del = <T = any>(url: string, data: AnyObject): Promise<T> => {
return request(url, 'DELETE', data, {})
}
export default {
get,
postJ,
postW,
putJ,
putW,
del
}
四.調(diào)用請求
接下來我們就根據(jù)上面封裝的請求來試一試效果吧,新建src/apis文件:文章來源:http://www.zghlxwxcb.cn/news/detail-487199.html
//引入封裝方法
import http from "@/request";
export const getTest = () => http.get<any>(`url`, {})
export const postTest = (data:any) => http.postJ<any>(`url`, data)
總結(jié)?
? ? ? ? 可以看到,封裝之后的請求已經(jīng)非常精簡,配置好各個環(huán)境地址,根據(jù)請求方式,數(shù)據(jù)格式,選擇對應(yīng)的封裝方法即可。文章來源地址http://www.zghlxwxcb.cn/news/detail-487199.html
到了這里,關(guān)于【uniapp&微信小程序】封裝uni.request()的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!