Vue-vben-admin Vue3+TS Axios的封装源码分析
前言
一、近期再用Vue3+TS 重构之前Vue2的项目,因此想着借鉴一下业界较为优秀的代码,在Git上面找了好久,经过同事推荐,我发现由anncwd出品的Vue-vben-admin是很不错的,截止目前在git上面已经有5.9k个star了,目前将这个模板看完了,我觉得里面写的最好的莫过于对于Axios的封装了,在此我简单对这个源码进行一个分析,里面也涉及一些TS+Vue3的知识点,最重要的是,能够发现其中写的特别优秀的地方,我们也可以运用在自己的项目当中。
1.我们先来看一下源码中的目录结构吧
2.目录分析,这个文件夹当中分为6个文件,其中index.ts是入口文件,Axios是主要的对于axios二次封装的类,axiosCancel是对于取消请求类canceler的封装,axiosTransform.ts是定义了一个类,涵盖所有对于数据处理无论错误还是失败的钩子函数,checkStatus.ts是对于后端返回code非200时的处理函数,helper是一个处理时间的函数,这6个文件相辅相成,构建了一个强大的axios的二次封装,接下来我们就来看一看其中每个文件的源码吧
二、index.ts
1.在看index.ts的源码之前我必须先带着大家补充几个知识点,以免其中有几个地方比较卡顿
(1)ts中的Partial<T>类,实际上在ts当中为我们提供了这样的一个类,Partial
它可以将接受一个T泛型,可以将T中的所有属性变为可选的,换句话说,任意类型的机构,经过Partial处理后,所有的内部属性就变为可选的了。
interface A {
a:string
b:number
}
const a:A = {
// error 因为A类型必须具备两个属性
a:'张三'
}
const b:Partial<A> = {
// successful 经过Partial处理后,所有属性值变为可选
a:'张三'
}
//看一下他的源码
type Partial<T> = {
[P in keyof T]?: T[P];
};
//其实就是给每一个属性加了一个?操作符而已,将所有属性变为非必须的了而已
(2)encodeURIComponent
//这个是JavaScript的原生Api ,可以把字符串作为 URI 组件进行编码。字母数字保持原来的样子,当时汉字或者其他所有符号都会将其编码为数字,字母或者%,
var uri="http://w3cschool.cc/my test.php?name=ståle&car=saab";
encodeURIComponent(uri)
// 输出:http%3A%2F%2Fw3cschool.cc%2Fmy%20test.php%3Fname%3Dst%C3%A5le%26car%3Dsaab
有了上面的补充,接下来就直接来看一下代码吧,我都做了注释,但是下面的代码会依赖一些类型或者函数,大家先过一下,我们主要看一下结构,开始吧
import {
AxiosTransform } from './axiosTransform'
import {
AxiosResponse, AxiosRequestConfig } from 'axios'
import {
Result, RequestOptions, CreateAxiosOptions } from './types'
import {
errorResult } from './const'
import {
ResultEnum, RequestEnum, ContentTypeEnum,} from '../../../enums/httpEnum'
import {
useMessage } from '@/hooks/web/useMessage'
import {
isString, isObject, isBlob } from '@/utils/is'
import {
formatRequestDate } from './helper'
import {
setObjToUrlParams, deepMerge } from '@/utils'
import {
getToken } from '@/utils/auth'
import {
checkStatus } from './checkStatus'
import VAxios from './Axios'
const {
createMessage, createErrorModal } = useMessage()
/**
* 请求处理
*/
const transform: AxiosTransform = {
// 所谓transform 本质上就是 transform 这个对象中拥有 多个处理数据的钩子
/**
* 请求成功处理
* 但依然要根据后端返回code码进行判断
*/
transformRequestData: ( // 对后端返回的数据做处理, 这是在http状态码为200的时候
res: AxiosResponse<Result>,
options: RequestOptions
) => {
const {
isTransformRequestResult } = options
if (!isTransformRequestResult) return res.data // 不处理 直接返回res.data
const {
data } = res
if (!data) return errorResult // 错误处理
const {
code, msg: message } = data
if (code === ResultEnum.UNLOGIN) {
const msg = '请重新登陆!'
createMessage.error(msg)
Promise.reject(new Error(msg))
location.replace('/login')
return errorResult
}
if (code === ResultEnum.BACKERROR) {
const msg = '操作失败,系统异常!'
createMessage.error(msg)
Promise.reject(new Error(msg))
return errorResult
}
const hasSuccess =
data && Reflect.has(data, 'code') && code === ResultEnum.SUCCESS // 200
if (!hasSuccess) {
// 非200 非 401 非500 的情况 直接返回后端提示的错误
if (message) {
if (options.errorMessageMode === 'modal') {
createErrorModal({
title: '错误提示', content: message })
} else {
createMessage.error(message)
}
}
Promise.reject(new Error(message))
return errorResult
}
if (code === ResultEnum.SUCCESS) return