uniapp
+ ts
+ vue3
发送请求方案
当你使用
uniapp
开发一个前端项目时,你可能需要向后端发送HTTP
请求获取数据并在页面中显示。如果你也在使用ts
编写代码并使用vue3
来构建组件的话,下面是一个完整的发送HTTP
请求的方案。
需要安装依赖luch-request
安装依赖
pnpm add luch-request --save
创建d.ts 全局文件
d.ts 文件就是ts全局可以使用的类型
declare namespace Api {
// 这个需要根据后端统一的 返回格式做修改
interface BasicInstance {
code: number;
msg: string;
extras: string;
time: string;
url?: string;
}
// 一样的,根据后端格式,比如有的后端会统一把数据放到 data 里,有的会放在 rows 里,调整即可
interface Response<T> extends BasicInstance {
data: T;
}
// 自定义配置,是否显示请求loading
interface Config {
notLoading: boolean;
}
// 分页配置
interface Pagination<T = any> {
code: number;
msg: boolean;
rows: T;
total: number;
}
}
封装全局请求入口
在根目录中创建
api
文件夹,添加request.ts
文件
import HttpRequest from "luch-request";
import { useAccountStore } from "@/store/useAccountStore";
import { Oops } from "@/hooks/Oops";
import { To } from "@/hooks/To";
import type { HttpRequestConfig, HttpResponse, HttpError, HttpTask } from "luch-request";
export const BASE_URL = "https://your.services.address.cn";
const requestInstence = new HttpRequest({
baseURL: BASE_URL,
timeout: 10 * 1000,
header: {
"Content-Type": "application/json;charset=utf-8"
}
});
requestInstence.interceptors.request.use(
(config: HttpRequestConfig) => {
const accountStore = useAccountStore();
const {
custom: { notLoading }
} = config as HttpRequestConfig & { custom: Api.Config };
// 默认需要Loading。。。
notLoading || uni.showLoading({ title: "加载中...", mask: true });
config.header = { ...config.header, Authorization: `Bearer ${accountStore.Token}` };
return config;
},
(error: HttpRequestConfig<HttpTask> | HttpError) => Promise.reject(error)
);
requestInstence.interceptors.response.use(
(response: HttpResponse) => {
const accountStore = useAccountStore();
uni.hideLoading();
const { data } = response;
if (data.code === 401) {
accountStore.clearToken();
uni.showModal({
title: "提示",
content: "身份认证失败,将跳转登录!",
showCancel: false,
success: (res) => {
if (res.confirm) {
To.go("/pages/login/index", { type: "reLaunch" });
}
}
});
}
return PoorCode200(data.code) && data;
},
(error: HttpError) => {
uni.hideLoading();
Oops.oh("网络君出小差了...");
return Promise.reject(error);
}
);
const PoorCode200 = (CODE: number) => CODE === 200 || 500;
export default requestInstence;
封装全局请求方法
有了上面的入口文件之后即可封装统一请求方法,也就是
get
,post
…
在api
文件夹中创建index.ts
文件
可以看到get
方法有连个参数,第二个为非必填,post
有三个参数,后两个为非必填,这里需要注意一下,第二个参数是提交的data
import http, { BASE_URL } from "./request";
import { useAccountStore } from "@/store/useAccountStore";
export type HttpData = Record<string | number | symbol, unknown>;
export const get = <T>(url: string, config?: Api.Config): Promise<Api.Response<T>> => http.get<T, Api.Response<T>>(url, { custom: config });
export function post<T>(url: string, data?: HttpData | ArrayBuffer, config?: Api.Config): Promise<Api.Response<T>> {
return http.post<T, Api.Response<T>>(url, data, { custom: config });
}
export function put<T>(url: string, data?: HttpData | ArrayBuffer, config?: Api.Config): Promise<Api.Response<T>> {
return http.put<T, Api.Response<T>>(url, data, { custom: config });
}
export function del<T>(url: string, config?: Api.Config): Promise<Api.Response<T>> {
return http.delete<T, Api.Response<T>>(url, { custom: config });
}
export function upload(tempPath: string): Promise<Api.BasicInstance> {
const accountStore = useAccountStore();
return new Promise((resolve) => {
uni.uploadFile({
url: `${BASE_URL}/common/upload`,
filePath: tempPath,
header: {
Authorization: `Bearer ${accountStore.Token}`
},
name: "file",
success: (res) => {
const { data, statusCode } = res;
if (statusCode === 200) {
return resolve(JSON.parse(data));
}
}
});
});
}
使用
在页面中使用的时候,只需要导入传入参数即可
import { get } from "@/api"
const getData = async () => {
// 这里使用了自定义配置,不需要loading,直接这样传就可以了,去掉的话默认是有全局loading的
const res = await get<BasicStatistic>("/system/execution/index", { notLoading: true });
if (res.code === 200) {
// 业务代码
}
};