当前位置: 首页 > article >正文

Vue中Axios二次封装

文章目录

  • 安装配置 axios
    • 安装 axios
    • 配置 axios
  • 创建 axios 实例
  • 使用
  • 请求

安装配置 axios

安装 axios

npm i axios -- save

配置 axios

创建目录 src/service/request,在该目录下配置 axios

type.ts 文件

import type { AxiosRequestConfig, AxiosResponse } from 'axios'

// 1.定义拦截器的类型, T 是响应res.data的类型
export interface HYRequestInterceptors<T = any> {
    requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
    requestInterceptorCatch?: (error: any) => any
    responseInterceptor?: (
        res: AxiosResponse<T>
    ) => AxiosResponse<T> | Promise<AxiosResponse<T>>
    responseInterceptorCatch?: (error: any) => any
}

export interface HYRequestConfig<T = any> extends AxiosRequestConfig {
    // 2.这里可以扩展自己的类型
    interceptors?: HYRequestInterceptors<T>
    showLoading?: boolean
}

config.ts 文件

const BASE_URL = "http://localhost:8080/api";
const TIME_OUT = 10000
export { BASE_URL, TIME_OUT }

index.ts 文件

import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { HYRequestInterceptors, HYRequestConfig } from './type'
// 导入ElLoading组件和样式
import 'element-plus/es/components/loading/style/css'
import {ElLoading, ElMessage} from 'element-plus'
const DEFAULT_LOADING = true

class HYRequest<T = any> {
    instance: AxiosInstance
    interceptors?: HYRequestInterceptors // 指定拦截器的类型
    showLoading?: boolean // 定义是否显示loading
    loading?: any // loading的组件实例
    constructor(config: HYRequestConfig<T>) {
        // 创建axios实例
        this.instance = axios.create(config)
        // 默认是否显示加载进度
        this.showLoading =
            config.showLoading === undefined ? DEFAULT_LOADING : config.showLoading // 默认为true

        // 从config中取出对应的实例的拦截器
        this.interceptors = config.interceptors
        // 如果某个实例的config中有定义拦截的回调函数,那么将这些函数添加到实例的拦截器中
        this.instance.interceptors.request.use(
            this.interceptors?.requestInterceptor,
            this.interceptors?.requestInterceptorCatch
        )
        this.instance.interceptors.response.use(
            this.interceptors?.responseInterceptor,
            this.interceptors?.responseInterceptorCatch
        )

        // 给所有实例添加全局的拦截器
        this.instance.interceptors.request.use(
            (config) => {
                // console.log('所有的实例都有的拦截器: 请求成功拦截')
                if (this.showLoading) {
                    this.loading = ElLoading.service({
                        lock: true,
                        text: '数据正在加载中....',
                        background: 'rgba(255, 255, 255, 0.7)',
                        fullscreen: false
                    })
                }
                return config
            },
            (err) => {
                return err
            }
        )

        this.instance.interceptors.response.use(
            (res) => {

                this.loading?.close() // 将loading移除
                // 这里还可以对返回的数据进行判断
                return res.data
            },
            (err) => {

                this.loading?.close() // 将loading移除
                // 例子: 判断不同的HttpErrorCode显示不同的错误信息

                if(err && err.response){
                    const status = err.response.status
                    switch (status) {
                        case 400:
                            ElMessage.error("请求错误");
                            break;
                        case 401:
                            ElMessage.error("未授权, 请重新登录");
                            break;
                        case 403:
                            ElMessage.error("登录过期, 请重新登录");
                            break;
                        case 404:
                            ElMessage.error("请求错误, 未找到相应的资源");
                            break;
                        case 408:
                            ElMessage.error("请求超时");
                            break;
                        case 500:
                            ElMessage.error("服务器错误");
                            break;
                        case 504:
                            ElMessage.error("网络超时");
                            break;
                        default:
                            ElMessage.error("请求失败");
                    }
                }
                return err
            }
        )
    }

    request<T = any>(config: HYRequestConfig): Promise<T> {
        return new Promise((resolve, reject) => {
            // 判断某个请求是否需要显示loading
            if (config.showLoading === false) {
                this.showLoading = config.showLoading
            }
            this.instance
                .request<T, T>(config)
                .then((res) => {
                    // 3.将结果resolve返回出去
                    resolve(res)
                })
                .catch((err) => {
                    reject(err)
                    return err
                })
                .finally(() => {
                    // 将showLoading设置true, 这样不会影响下一个请求
                    this.showLoading = DEFAULT_LOADING
                })
        })
    }

    get<T = any>(config: HYRequestConfig<T>): Promise<T> {
        return this.request<T>({ ...config, method: 'GET' })
    }
    post<T = any>(config: HYRequestConfig<T>): Promise<T> {
        return this.request<T>({ ...config, method: 'POST' })
    }
    delete<T = any>(config: HYRequestConfig<T>): Promise<T> {
        return this.request<T>({ ...config, method: 'DELETE' })
    }

    patch<T = any>(config: HYRequestConfig<T>): Promise<T> {
        return this.request<T>({ ...config, method: 'PATCH' })
    }
}

export default HYRequest

创建 axios 实例

src/service 下创建文件

inex.ts 文件

// service统一出口
import HYRequest from './request'
import { BASE_URL, TIME_OUT } from './request/config'

const http = new HYRequest({
    baseURL: BASE_URL,
    timeout: TIME_OUT,
    // showLoading: true, // 全局配置显示loading
    interceptors: {
        requestInterceptor: (config) => {
            // 携带token的拦截
            const token = localStorage.getItem('token')
            if (token && config.headers) {
                config.headers.Authorization = `Bearer ${token}`
            }
            return config
        },
        requestInterceptorCatch: (err) => {
            // console.log('单个实例-请求失败的拦截')
            return err
        },
        responseInterceptor: (res) => {
            // console.log('单个实例-响应成功的拦截')
            return res
        },
        responseInterceptorCatch: (err) => {
            // console.log('单个实例-响应失败的拦截')
            return err
        }
    }
})

export default http

types.ts 文件

export interface IDataType<T = any>{
    code: number
    flag: boolean
    data: T
}

使用

service 下创建目录,每个目录对应于使用的模块即可,比如这里使用 user 作为目录。

types.ts

export interface IUserInfo{
    name: string
    email: string
}

user.ts

import http from '../index'
import {IDataType} from "../types";
import {IUserInfo} from "./types";

enum UserAPI{
    UserInfo = '/user/info'
}

export function requestUserInfo(){
    return http.get<IDataType<IUserInfo>>({
        url: UserAPI.UserInfo,
        //showLoading: false // 是否需要显示 loading 样式
    })
}

请求

一个 vue 文件

<template>
  <div>
    <h1>Axios 请求示例</h1>
    <div v-if="userInfo">
      <p>用户名: {{ userInfo.name }}</p>
      <p>邮箱: {{ userInfo.email }}</p>
    </div>
  </div>
</template>

<script lang="ts" setup>


import {onMounted, reactive} from "vue";
import {requestUserInfo} from "./service/user/user";

let userInfo = reactive({name: '', email: ''});

onMounted(() => {
  requestUserInfo().then(res => {
    Object.assign(userInfo, res.data);
  })
})

</script>
<style>
</style>

http://www.kler.cn/a/445109.html

相关文章:

  • 【Rust自学】4.4. 引用与借用
  • go-zero(十五)缓存实践:分页列表
  • 批量DWG文件转dxf(CAD图转dxf)——c#插件实现
  • AI开发-语料-“self-instruct”
  • 华为云计算HCIE笔记01
  • 力扣438-找到字符串中所有字母异位词
  • 主曲率为常数时曲面分类
  • uniApp使用腾讯地图提示未添加maps模块
  • 设计模式--单例模式【创建型模式】
  • uniapp图片数据流���� JFIF ��C 转化base64
  • Ubuntu将深度学习环境配置移植到新电脑
  • 分布式锁介绍
  • Spark 运行时对哪些数据会做缓存?
  • 怎样衡量电阻负载的好坏
  • (六)Spring Cloud Alibaba 2023.x:Sentinel 流量控制与熔断限流实现
  • 2024年12月16日Github流行趋势
  • mfc140.dll文件缺失的修复方法分享,全面分析mfc140.dll的几种解决方法
  • 如何使用git新建本地仓库并关联远程仓库的步骤(详细易懂)
  • LoadBalancer负载均衡和Nginx负载均衡区别理解
  • ubuntu解决ssh连接:Permission denied (publickey)
  • 【Linux】AlmaLinux 9.5虚拟机安装过程记录分享
  • ubuntu--用户
  • 【vue】npm install 报错 python2 Error: not found: python2
  • Day27 C++ 动态内存
  • ArcGIS Pro 3.4新功能3:空间统计新特性,基于森林和增强分类与回归,过滤空间自相关
  • CTFHUB 历年真题 afr-1