1. 定义 .env.development
- 方便于全局引入变量
- 对.env , .env.[不同环境] 进行环境隔离
VITE_APP_API=https://xxx
VITE_APP_API_TIMEOUT=10 # x * 1000 = x seconds
2. 工具类(包含拦截器,类型接口)
- 封装 uniapp.request 简化 http请求,
- Ts 泛型化
- 全局业务状态码捕获
// 1.引入Env变量
const API = import.meta.env.VITE_APP_API;
const API_TIMEOUT = import.meta.env.VITE_APP_API_TIMEOUT;
// 2.uniapp 拦截器
uni.addInterceptor('request', {
invoke(options) {
// 请求前对请求头操作 , 如添加校验请求头 Authorization
},
success(response) {
// 请求成功操作
},
fail(err) {
// 请求网络异常操作
console.log('interceptor-fail', err);
},
complete(res) {
// console.log('interceptor-complete', res);
},
});
// 3. 通用返回接口
// 可放 types/global.d.ts [declare 声明]。这里方便展示
interface Response<T = unknown> {
code: number;
msg: string;
result: T;
}
/**
* 默认状态码
*/
const STATUS_CODE = {
SUCCESS: 200,
FAIL: 400,
};
/**
* 对 uni.request 进行工具封装
*
* @param option {{@link UniNamespace.RequestOptions}}
*/
const useHttp = <T>(option: UniNamespace.RequestOptions) => {
return new Promise<Response<T>>((resolve, reject) => {
uni.request({
...option,
success(res) {
// 业务判断成功
const result = res.data as Response<T>;
resolve(result);
// ....省略
// 业务判断失败
reject(res);
},
fail(err) {
// 请求网络异常操作
reject(err);
},
});
});
};
// GET 请求封装, Omit 排除 method 类型
const useHttpGet = <T>(option: Omit<UniNamespace.RequestOptions, 'method'>) => {
return useHttp<T>({
...option,
method: 'GET',
});
};
// POST 请求封装, Omit 排除 method 类型
const useHttpPost = <T>(
option: Omit<UniNamespace.RequestOptions, 'method'>
) => {
return useHttp<T>({
...option,
method: 'POST',
});
};
export { useHttp, useHttpGet, useHttpPost, STATUS_CODE };
export type { Response };
3. Api函数
- 简化网络请求流程
import { useHttp } from '@/utils/httpClient';
/**
* 获取用户信息
*
* @param username 用户名
* @return Promise<Response<string>>
*/
export const getUserDataApi = (username: string) => {
return useHttpGet<string>({
url: '/user',
data: {
username,
},
});
};
引入 vue-request 三方网络请求库
官网: [cn.attojs.org/guide/intro…]
npm install vue-request
使用案例
进一步简化数据的获取,需根据 Response 接口定义
import type { Ref } from 'vue';
import { computed } from 'vue';
import type { Response } from '@/utils/httpClient';
type R<T> = Ref<Response<T> | undefined>;
/**
* 简化获取请求列表数据的逻辑
*
* @param response 响应数据
* @param defaultVal 默认值
* @return 业务数据 response?.value?.data
*/
export const useDataList = <T>(response: R<T>, defaultVal = <T>[]) => {
return computed<T>(() => {
return response?.value?.result || defaultVal;
});
};
/**
* 简化获取请求数据的逻辑
*
* @param response 响应数据
* @param defaultVal 默认值
* @return 业务数据 response?.value?.data
*/
export const useData = <T>(response: R<T>, defaultVal = <T>{}) => {
return computed<T>(() => {
return response?.value?.result || defaultVal;
});
};
Vue3.2 中使用
import { getUserDataApi } from '@/services/api/user';
import { useData } from '@/hooks/useResponse';
// 默认 manual: false, 自动请求
<script lang="ts" setup>
const { data: hotRes, loading } = useRequest(getUserDataApi);
const userData = useData(hotRes); // ts -> userData: string
</script>
<template>
<view>
是否加载中: {{ loading }}
用户的数据: {{ userData }}
</view>
</template>
<style lang="scss"></style>