小白系列Vite-Vue3-TypeScript:007-配置axios并封装api

news2025/6/2 1:21:05

上一篇我们介绍了Vite+Vue3+TypeScript项目中Element Plus的安装和配置,本篇我们来介绍一下如何配置axios并封装api。

axios是一个基于promise的HTTP库,可以用在浏览器和node.js中,其最大的亮点就是支持了ES6里的Promise Api。废话不多说,直接撸起来......

安装axios

有时候可能需要对请求或者相应参数进行解析或者格式转换,所以除了axios库之外,一般我们还会安装qs(一个流行的查询参数序列化和解析库),qs可以将一个普通的object序列化成一个查询字符串,或者反过来将一个查询字符串解析成一个object,而且支持复杂的嵌套。

//安装axios
npm i axios -S

//安装qs
npm i qs -S

配置vite环境变量(区分开发和生产环境)

创建环境文件

项目根目录下创建文件 .env.dev(开发测试环境)和文件 .env.prod(生产环境)

.env.dev文件代码如下

#(.env.dev 测试/开发环境变量配置)
VITE_ENV = development

# base api

# 初始地址, 注意端口号要与vite.config.ts的server部分一致
VITE_SOURCE_URL = http://localhost:8088

# 基础域名
VITE_BASE_API = http://localhost:8088

# 服务地址
VITE_SERVE_ADD = /api

.env.prod文件代码如下

#(.env.prod 生产环境变量配置)
VITE_ENV = development

# base api

# 初始地址, 注意端口号要与vite.config.ts的server部分一致
VITE_SOURCE_URL = http://192.168.5.106:8088

# 基础域名
VITE_BASE_API = http://192.168.5.106:8088

# 服务地址
VITE_SERVE_ADD = /api

更新指令

修改package.js的脚本命令内容

"scripts": {
  "dev": "vite --mode dev",
  "prod": "vite --mode prod",
  "build": "vue-tsc && vite build --mode prod",
  "preview": "vite preview"
},

这样配置完成后,运行npm run dev或npm run prod或build时会把自定义的环境变量载入进去,避免了每次打包和开发都要临时修改变量的尴尬。

创建config.ts配置文件

上面我们已经创建好了环境变量,在src目录下新建config.ts文件来接收环境变量以及后面可能出现的公用配置。

/** 环境变量 */
const ENV = import.meta.env;  // vite是以这种方式获取环境变量

/** 基础域名 */
export const SOURCE_URL = ENV.VITE_SOURCE_URL;
export const BASE_URL = ENV.VITE_BASE_API;

/** 基础服务地址 */
export const URL = BASE_URL + '/api';

/** 超时时间 */
export const TIMEOUT = 6000;

这样在后面创建axios实例和封装api的时候,就可以直接通过config.ts文件来读取配置了。

创建axios实例文件

在项目src/utils目录下(没有的话创建即可)新建request.ts文件,这个文件就是我们要书写axios的api封装。封装过程中用到了Message组件,刚好上一篇我们已经介绍了安装及配置ElementPlus的过程。同时引入token管理。

导入所需依赖

import axios, { AxiosRequestConfig } from 'axios'
import qs from 'qs'
import { setLocalStorage, getLocalStorage } from './localstorage'
import { BASE_URL, TIMEOUT, SOURCE_URL } from "@/config";

导入qs的时候一般情况下,编辑器会报错“无法找到模块“qs”的声明文件

因为TypeScript中s不能直接这样引入js类型库,解决方法:在src目录下新建一个globe.d.ts,添加如下代码即可

declare module "qs"

创建实例

const instance = axios.create({
    baseURL: BASE_URL,
    timeout: TIMEOUT,
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
})

配置请求拦截器

// http request 请求拦截器
instance.interceptors.request.use(
    config => {
        config.headers.AcceptLanguage = getLocalStorage("locale");
        if (localStorage.myToken) {
            config.headers.Authorization = getLocalStorage("myToken");
        }
        return config
    },
    err => {
        return Promise.reject(err)
    }
)

配置响应拦截器

// http response 响应拦截器
instance.interceptors.response.use(
    response => {
        return handleData(response.data)
    },
    error => {
        const errData = error.response.data
        if (errData.status === 500) {
            setLocalStorage('myToken');
            window.location.href = sourceUrl;
        }
        let err = errData.message;
        if (err != '' && err != null && err != undefined) {
            ElMessage({
                type: 'error',
                message: errData.message
            })
            return Promise.reject(errData)
        } else {
            ElMessage({
                type: 'error',
                message: 'HTTP:服务器遇到错误,请求失败。'
            })
        }
    }
)

封装API

// API封装
const get = async (url: string) => {
    /**
     ......
     可以在这里自定义封装处理方法
     ......
     */
    try {
        return await instance
            .get(url)
    } catch (error) {
        return handleError(error)
    }
}

完整代码

request.ts

import axios, { AxiosRequestConfig } from 'axios'
import qs from 'qs'
import { setLocalStorage, getLocalStorage } from './localstorage'
import { BASE_URL, TIMEOUT, SOURCE_URL } from "@/config";
const instance = axios.create({
    baseURL: BASE_URL,
    timeout: TIMEOUT,
    headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    }
})
// http request 请求拦截器
instance.interceptors.request.use(
    config => {
        config.headers.AcceptLanguage = getLocalStorage("locale");
        if (localStorage.myToken) {
            config.headers.Authorization = getLocalStorage("myToken");
        }
        return config
    },
    err => {
        return Promise.reject(err)
    }
)
// http response 响应拦截器
instance.interceptors.response.use(
    response => {
        return handleData(response.data)
    },
    error => {
        const errData = error.response.data
        if (errData.status === 500) {
            setLocalStorage('myToken');
            window.location.href = SOURCE_URL;
        }
        let err = errData.message;
        if (err != '' && err != null && err != undefined) {
            ElMessage({
                type: 'error',
                message: errData.message
            })
            return Promise.reject(errData)
        } else {
            ElMessage({
                type: 'error',
                message: 'HTTP:服务器遇到错误,请求失败。'
            })
        }
    }
)

// API封装
const get = async (url: string) => {
    /**
     ......
     可以在这里自定义封装处理方法
     ......
     */
    try {
        return await instance
            .get(url)
    } catch (error) {
        return handleError(error)
    }
}
const post = async (url: string, data?: any, config?: AxiosRequestConfig<any> | undefined) => {
    /**
    ......
    可以在这里自定义封装处理方法
    ......
    */
    try {
        return await instance
            .post(url, data, config)
    } catch (error) {
        return handleError(error)
    }
}
const deleteFn = async (url: string, config?: AxiosRequestConfig<any> | undefined) => {
    /**
    ......
    可以在这里自定义封装处理方法
    ......
    */
    try {
        return await instance
            .delete(url, config)
    } catch (error) {
        return handleError(error)
    }
}
const postJSON = async (url: string, data?: any, config?: AxiosRequestConfig<any> | undefined) => {
    /**
    ......
    可以在这里自定义封装处理方法
    ......
    */
    data = qs.stringify(data);
    try {
        return await instance
            .post(url, data, config)
    } catch (error) {
        return handleError(error)
    }
}
const patchFn = async (url: string, data?: any, config?: AxiosRequestConfig<any> | undefined) => {
    /**
    ......
    可以在这里自定义封装处理方法
    ......
    */
    try {
        return await instance
            .patch(url, data, config)
    } catch (error) {
        return handleError(error)
    }
}
// 对请求返回的错误进行自处理
function handleError(error: any) {
    return error
}
// 对响应的数据进行自处理
function handleData(data: any) {
    return data
}
export default {
    get: get,
    post: post,
    postJSON: postJSON,
    delete: deleteFn,
    patch: patchFn
}

localstorage.ts


export const setLocalStorage = (key: string, value?: string, hours?: number) => {
    value = JSON.stringify(value);
    // 设置过期原则
    if (!value) {
        localStorage.removeItem(key)
    } else {
        let Hours = hours || 24; // 以小时为单位,默认24小时
        let exp = new Date();
        localStorage[key] = JSON.stringify({
            value,
            expires: exp.getTime() + Hours * 1000 * 60 * 60,//失效时间
        })
    }
}
export const getLocalStorage = (key: string) => {
    try {
        let ls = JSON.parse(localStorage[key]);
        if (!ls || ls.expires < Date.now()) {
            return ''
        } else {
            return JSON.parse(ls.value)
        }
    } catch (e) {
        // 兼容其他localstorage
        return localStorage[key]
    }
}

config.ts

/** 环境变量 */
const ENV = import.meta.env;  // vite是以这种方式获取环境变量

/** 基础域名 */
export const SOURCE_URL = ENV.VITE_SOURCE_URL;
export const BASE_URL = ENV.VITE_BASE_API;

/** 基础服务地址 */
export const URL = BASE_URL + '/api';

/** 超时时间 */
export const TIMEOUT = 6000;

OK,这样基本就完成了axios的安装和api封装了!

我相信,每天学习一点点,收获成长亿点点!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/334724.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Node =>Express学习

1.Express 能做什么 能快速构建web网站的服务器 或 Api接口的服务期 Web网站服务器&#xff0c;专门对外提供Web网页资源的服务器Api接口服务器&#xff1a;专门对外提供API接口的服务器 2.安装 在项目所处的目录中&#xff0c;运行以下命令&#xff0c;简装到项目中了 npm …

ChatGPT与马斯克 在 “ 遥感 ” 中的初探索

有人说&#xff1a;一个人从1岁活到80岁很平凡&#xff0c;但如果从80岁倒着活&#xff0c;那么一半以上的人都可能不凡。 生活没有捷径&#xff0c;我们踩过的坑都成为了生活的经验&#xff0c;这些经验越早知道&#xff0c;你要走的弯路就会越少。 1前言 文章开始前&#x…

栈和队列基本原理

栈和队列基本原理1.栈1.1 栈基本原理1.2. 栈操作步骤1.2.1 插入数据流程【压栈】1.2.2 移除数据流程【出栈】1.3. 栈代码实现2.队列2.1 队列基本原理2.2 队列操作步骤2.2.1 插入数据2.2.2 移除数据2.3. 队列代码实现3.栈与队列对比1.栈 1.1 栈基本原理 栈顶【末尾】&#xff…

突破边界:“超融合+”带来的商业化精益之路

相信大家都看了《流浪地球2》&#xff0c;其中人类一次次超越极限&#xff0c;以勇气和责任完成伟大征程的情节让我们深深感动。在现实的科技发展中&#xff0c;我们可能不会像科幻作品那样完成惊险万分地完成突破。但超越极限&#xff0c;却时时刻刻发生在科技产业当中。“超融…

K_A12_002 基于STM32等单片机采集光敏电阻传感器参数串口与OLED0.96双显示

K_A12_002 基于STM32等单片机采集光敏电阻传感器参数串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RC光敏电阻传感器模块1.2、STM32F103C8T6光敏电阻传感器模块五、基…

星河案例 | 冲量在线助力中国电信打造数据要素融通与AI能力开放外拓新范式

2022 年大数据“星河”案例征集活动由中国信息通信研究院、中国通信标准化协会大数据技术标准推进委员会(CCSA TC601)共同组织&#xff0c;旨在促进大数据技术产品及相关产业发展&#xff0c;加快培育数据要素市场、充分发挥数据作为生产要素的独特价值&#xff0c;树立行业标杆…

OnGUI Box 控件||Unity 3D OnGUI 常用控件

OnGUI Box 控件Unity 3D Box 控件用于在屏幕上绘制一个图形化的盒子。Box 控件中既可以显示文本内容&#xff0c;也可以绘制图片&#xff0c;或两者同时存在。GUIContent 和 GUIStyle 对于 Box 控件同样适用&#xff0c;既可以用来修饰 Box 控件的文本颜色&#xff0c;也可以用…

第2章 信息系统项目管理基础

项目管理基础 项目的概念 项目是为提供一项独特产品、服务或成果所做的临时性努力。 项目的特点 主要特点&#xff08;PMI归纳的&#xff09; 临时性&#xff0c;独特的产品、服务或成果&#xff0c;逐步完善其他特点 资源约束&#xff1a;资源成本是项目成功实施的约束条件之…

预测物联网设备健康状态,你可能需要这套解决方案

1. 应用场景随机振动[注1]会发生在工业物联网的各个场景中&#xff0c;包括产线机组设备的运行、运输设备的移动、试验仪器的运行等等。通过分析采集到的振动信号可以预估设备的疲劳年限、及时知晓设备已发生的异常以及预测未来仪器可能发生的异常等等。本篇教程会提供给有该方…

小白系列Vite-Vue3-TypeScript:008-安装配置mock

上一篇我们介绍了ViteVue3TypeScript项目中axios的安装和配置&#xff0c;并手动封装了api。本篇我们来在上篇基础上介绍如何引入mock&#xff0c;并在本地模拟后台接口请求来达到本地测试的目的。在现在前后端分离的开发模式中&#xff0c;前端页面很多渲染的数据都需要通过ht…

仿真及设计工具下载安装方法详细说明

标题仿真及设计工具下载安装方法详细说明 软件的下载&#xff1a; 物流仿真的软件下载请进入&#xff1a;链接: https://pan.baidu.com/s/12iP3TTkXw-D5DAMu3mQbwQ 提取码: 8888里面放置了所有版本的软件 可以根据自己的使用环境进行选择下载最新版本。软件的安装&#xff1a…

CUDA中的图内存节点

CUDA中的图内存节点 文章目录CUDA中的图内存节点1. 简介2. 支持的架构和版本3. API基础知识3.1. 图节点 APIs3.2. 流捕获3.3. 在分配图之外访问和释放图内存3.4. cudaGraphInstantiateFlagAutoFreeOnLaunch4. 优化内存复用4.1. 解决图中的重用问题4.2. 物理内存管理和共享5. 性…

C. Least Prefix Sum codeforces每日一题

&#x1f680;前言 &#x1f680; 大家好啊&#xff0c;这里是幸麟 &#x1f9e9; 一名普通的大学牲&#xff0c;最近在学习算法 &#x1f9e9;每日一题的话难度的话是根据博主水平来找的 &#x1f9e9;所以可能难度比较低&#xff0c;以后会慢慢提高难度的 &#x1f9e9;此题标…

ImportError: /lib64/libm.so.6: version `GLIBC_2.23‘ not found问题解决方法

1.环境&#xff1a;Centos7&#xff0c;GCC version 9.1.0&#xff0c;python3.7&#xff0c;TensorFlow1.14.0.因为/usr/lib64/libstdc.so.6: version CXXABI_1.3.8 not found问题&#xff0c;我将GCC版本升级到了9.1.0&#xff0c;但是运行TensorFlow的时候出现了ImportError…

网页CAD开发快速入门

演示说明 提示:目前提供两种在网页中浏览编辑CAD图纸方案&#xff0c;详细说明见&#xff1a;MxDraw帮助 网页中打开CAD最简步骤&#xff1a; 第一步: 安装插件运行环境&#xff0c;下载安装(可能需要退杀毒软件)&#xff1a;https://demo.mxdraw3d.com:3562/MxDrawx86Setup…

Python语言零基础入门教程(十一)

Python 列表(List) 序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置&#xff0c;或索引&#xff0c;第一个索引是0&#xff0c;第二个索引是1&#xff0c;依此类推。 Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。 序列都可以…

springboot 关闭所有日志,包括起始springboot图标和运行输入日志

关闭所有日志分2部分: 1 关闭运行输出日志 , 2 关闭springboot启动图标 1 关闭运行输出日志 (这里没有使用日志框架设置日志) 在 application.properties 中 添加 logging.level.你自己项目的包名off例如&#xff1a;logging.level.com.example.licenseoff 注&#xff1a;of…

leetcode 2306. Naming a Company(命名公司)

字符串ideas中有一系列的名字&#xff0c;用这些名字给公司命名&#xff0c;命名规则如下&#xff1a; 在ideas中选出2个不同的单词&#xff0c;交换它们的首字母&#xff0c; 交换首字母后的两个单词如果不和ideas中的任一单词相同&#xff0c;那么就可以用它们命名&#xff0…

Vue - 驼峰和短横线分割命名注意事项

Vue - 驼峰和短横线分割命名注意事项一. 驼峰和短横线分割命名注意事项1.1 组件注册命名1.2 父子组件数据传递时命名1.3 父子组件函数传递一. 驼峰和短横线分割命名注意事项 我们一般定义组件的方式有两种&#xff1a; 短横线分隔命名&#xff1a;kebab-case。首字母大写命名…

【实际开发17】- 静态测试

静态测试技术&#xff1a;不运行被测试程序&#xff0c;对代码通过检查、阅读进行分析。 目录 1. 静态测试 1. 静态测试三步曲 : 走查 / 审查 / 评审 2. 编码的标准和规范 3. 代码评审 1. 代码走查 ( Walk Through ) 2. 正式会议审查 ( Inspection ) 3. 评审 ( Review )…