目录
前言
配置Axios实例
页面使用
总结
前言
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。它提供了一种简单、一致的 API 来处理HTTP请求,支持请求和响应的拦截、转换、取消请求等功能。关于它的作用:
-
发起 HTTP 请求: Axios 提供了丰富的 API,使得在浏览器和 Node.js 中发起 HTTP 请求变得非常容易。可以发送 GET、POST、PUT、DELETE 等不同类型的请求。
-
Promise 风格: Axios 使用 Promise 风格的 API,使得在异步请求中更容易处理数据和错误。可以使用 .then() 处理成功的响应,使用 .catch() 处理错误。
-
拦截请求和响应: 可以在请求和响应被发送或接收之前进行拦截处理。这使得在请求发送前或响应返回后可以进行一些全局的处理,比如添加请求头、处理错误等。
-
自动转换 JSON 数据: Axios 在接收到响应数据时,会自动将 JSON 字符串转换为 JavaScript 对象。这样可以方便地处理和操作服务器返回的 JSON 数据。
-
取消请求: Axios 允许你创建一个取消请求的令牌,以便在需要时取消尚未完成的请求。这在处理组件销毁或用户导航时非常有用,可以避免不必要的请求。
-
全局配置: 可以配置全局的默认值,例如基础URL、超时时间等,以便在整个应用程序中使用相同的设置。
-
处理请求和响应数据: 可以在请求和响应时对数据进行转换和处理。这包括序列化请求数据、解析响应数据等。
-
上传和下载进度: Axios 提供了上传和下载进度的事件,可以监视请求和响应的进度。这对于实时显示进度条等功能非常有用。
总体而言,Axios是一个强大而灵活的工具,可以简化和优化HTTP请求的处理,是前端开发中常用的网络请求库之一,并且当在Vue.js 3项目中使用Axios时,可以通过全局设置来配置Axios实例,以便在整个应用程序中共享相同的请求和响应逻辑,比如500或者401时,系统的一些操作。
配置Axios实例
前提,需要先安装axios:npm install axios
如下:
开始配置,先在项目的一个文件夹下某创建一个文件,里面进行Axios 实例配置,通常在src/utils下,一般内容有:
import axios from 'axios'; // 创建 Axios 实例 const service = axios.create({ baseURL: process.env.VUE_APP_BASE_URL, // 使用环境变量配置 baseURL timeout: 5000, // 设置请求超时时间 }); // 请求拦截器 service.interceptors.request.use( (config) => { // 在请求发送前可以进行一些配置,例如添加认证信息等 config.headers['X-Auth-Token'] = 'your_token'; // 示例:添加认证信息 return config; }, (error) => { return Promise.reject(error); } ); // 响应拦截器 service.interceptors.response.use( (response) => { // 在响应返回后,可以进行一些处理,例如判断是否需要更新令牌等 // ... return response; }, (error) => { // 处理响应错误 // ... return Promise.reject(error); } ); export default service;
上面是比较基础的,可以在此基础上进行自定义的操作,比如我下面这种:
axios-req.ts
import axios from 'axios' import { ElLoading, ElMessage, ElMessageBox } from 'element-plus' import { useBasicStore } from '@/store/basic' //使用axios.create()创建一个axios请求实例 const service = axios.create() let loadingInstance: any = null //loading实例 let tempReqUrlSave = '' let authorTipDoor = true const noAuthDill = () => { authorTipDoor = false ElMessageBox.confirm('请重新登录', { confirmButtonText: '重新登录', closeOnClickModal: false, showCancelButton: false, showClose: false, type: 'warning' }).then(() => { useBasicStore().resetStateAndToLogin() authorTipDoor = true }) } //请求前拦截 service.interceptors.request.use( (req: any) => { const { token, axiosPromiseArr }: any = useBasicStore() //axiosPromiseArr收集请求地址,用于取消请求 req.cancelToken = new axios.CancelToken((cancel) => { tempReqUrlSave = req.url axiosPromiseArr.push({ url: req.url, cancel }) }) //设置token到header if (token) req.headers['X-Auth-Token'] = token //如果req.method给get 请求参数设置为 ?name=xxx if ('get'.includes(req.method?.toLowerCase()) && !req.params) req.params = req.data //req loading // @ts-ignore if (req.reqLoading ?? true) { loadingInstance = ElLoading.service({ lock: true, fullscreen: true, // spinner: 'CircleCheck', text: '数据载入中...', background: 'rgba(0, 0, 0, 0.1)' }) } return req }, (err) => { //发送请求失败 Promise.reject(err) } ) //请求后拦截 service.interceptors.response.use( (res: any) => { //取消请求 useBasicStore().remotePromiseArrByReqUrl(tempReqUrlSave) if (loadingInstance) { loadingInstance && loadingInstance.close() } //download file if (res.data?.type?.includes("sheet")) { return res } const { code, msg } = res.data const successCode = [0,200,20000] const noAuthCode = [401,403] if (successCode.includes(code)) { return res.data } else { //authorTipDoor 防止多个请求 多次alter if (authorTipDoor) { if (noAuthCode.includes(code)) { noAuthDill() } else { // @ts-ignore if (!res.config?.isNotTipErrorMsg) { ElMessage.error({ message: msg, duration: 2 * 1000 }) } else { return res } return Promise.reject(msg) } } } }, //响应报错 (err) => { //取消请求 useBasicStore().remotePromiseArrByReqUrl(tempReqUrlSave) if (loadingInstance) { loadingInstance && loadingInstance.close() } ElMessage.error({ message: err, duration: 2 * 1000 }) return Promise.reject(err) } ) //导出service实例给页面调用 , config->页面的配置 export default function axiosReq(config) { return service({ baseURL: import.meta.env.VITE_APP_BASE_URL, timeout: 8000, ...config }) }
之后我们可以在api文件夹下新建一个user.ts,放一些API。就像这样:
import axiosReq from '@/utils/axios-req' //登录 export const loginReq = (subForm) => { return axiosReq({ url: '/login', method: 'post', data: subForm }) } //退出登录 export const loginOutReq = () => { return axiosReq({ url: '/loginOut', method: 'post' }) }
页面使用
这里以登录页为例
登录页面发送请求,一般会发送用户账号密码,然后获取到一个token,所以我一般这样用:
import { loginReq } from '@/api/user' const loginFunc = () => { loginReq({ username: subForm.keyword, password: subForm.password }) .then(({ data }) => { elMessage('登录成功') basicStore.setToken(data?.token) router.push('/') }) .catch((err) => { tipMessage.value = err?.msg }) .finally(() => { subLoading.value = false }) }
总结
如果想在Vue全局使用的话,可以用provide和inject来在整个应用程序中提供和注入Axios实例。
import { createApp } from 'vue'; import App from './App.vue'; import request from '@/utils/request'; const app = createApp(App); // 提供Axios实例 app.provide('request', request); app.mount('#app');
页面使用:
export default { inject: ['request'], methods: { fetchData() { this.request.get('/api/data') .then(response => { // 处理响应数据 }) .catch(error => { // 处理请求错误 }); }, }, };
但是还是建议每个页面需要哪些API就引入哪些吧。
总结,aixos的全局配置会方便API管理,并且对于一些关于 token 处理和错误处理的逻辑,以及状态码的反馈都是比较方便的,根据项目需求来实现。