赞
踩
在上文中,我们封装了统一的后端数据返回结果,有了标准化的接口数据,我们就可以针对它,在前端发送接收时,进行预处理。
通常在一个企业级或者个人开源的项目中,Axios会被二次封装。
二次封装的好处有哪些呢?
url
配置api
请求request
(请求)拦截器,例如:带上token
等,设置请求头response
(响应)拦截器,例如:统一错误处理,页面重定向等http错误码
(code错误码
)话不多说,我们直接开始吧!
创建src\utils\axiosUtil.js
。
这个文件就是用来封装Axios,我们想要在其他文件中使用Axios,这里我们就需要创建并抛出一个Axios实例。
import axios from 'axios'
import { ElMessage , ElNotification } from 'element-plus'
let axiosUtil = axios.create({
})
export default axiosUtil;
接下来,我们就开始进行配置。打开http://axios-js.com/zh-cn/docs/index.html#请求配置查看Axios提供的配置项。
首先,我们需要配置的是统一的请求接口。我们在测试test接口时直接使用Axios发GET请求http://localhost:8080/test
,这里的http://localhost:8080/
就是一个统一的Url。
let axiosUtil = axios.create({
baseURL:'http://localhost:8080',
})
有了这个baseURL在发送post请求的时候,就不需要加上http://localhost:8080/
,Axios会自动给我们加上!!!
.env
文件与环境变量但是http://localhost:8080/
这个只是本地测试的接口,我们还有服务器测试接口,上线后的接口。针对不同接口,我们每次都需要修改,是一件很麻烦的事情,还好我们使用的是Vite作为的辅助开发工具。
Vite 使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量:
.env # 所有情况下都会加载
.env.local # 所有情况下都会加载,但会被 git 忽略
.env.[mode] # 只在指定模式下加载
.env.[mode].local # 只在指定模式下加载,但会被 git 忽略
这里的模式通常包含:
也就是说我们需要在根目录下新建对应的**.env**文件
大家打开package.json文件,会看到以下命令
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
当我们在命令行执行yarn dev
或yarn run dev
,其实是执行vite
默认情况下,dev
命令 运行在 development
(开发) 模式,而 build
命令和preview
命令则运行在 production
(生产) 模式。
"scripts": {
"dev": "vite --mode development",
"build": "vite build --mode production",
"preview": "vite preview --mode production "
},
在**.env**文件中,我们可以编写额外的环境变量。为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_
为前缀的变量才会暴露给经过 vite 处理的代码。
例如:
VITE_APP_TITLE= 个人博客
VITE_APP_BASE_API= 'http://localhost:8080'
当我们执行命令的时候,Vite 暴露环境变量到一个特殊的 import.meta.env
对象上。我们可以通过这个对象来获取编写的环境变量。
新建.env
文件
VITE_APP_TITLE= 个人博客
VITE_APP_BASE_API= 'http://localhost:8080'
我们刚才说了,import.meta.env
挂着我们编写的环境变量。
我们修改axiosUtils
let axiosInstance = axios.create({
baseURL:import.meta.env.VITE_APP_BASE_API,
})
https://cn.vitejs.dev/guide/env-and-mode.html#env-variables
我们后端支持支持什么格式的数据,这里就可以指定具体的Content-type。我们这个项目就指定json即可
import axios from 'axios'
import { ElMessage , ElNotification } from 'element-plus'
import axios from "axios"
let axiosUtil = axios.create({
baseURL:import.meta.env.VITE_APP_BASE_API,
headers:{
"Content-type":"application/json"
}
})
一个请求超过一段时间自动停止。
import axios from 'axios'
import { ElMessage , ElNotification } from 'element-plus'
let axiosUtil = axios.create({
baseURL:import.meta.env.VITE_APP_BASE_API,
headers:{
"Content-type":"application/json"
}
timeout: 10000,
})
在请求发出之前,抽离出共同的方法。
例如 对于所有的psot请求,我们可能需要去进行序列化参数(后端要求序列化的参数),
又例如,我们发送的请求是错误的,我们要如何处理。
又又例如:我们的请求接口是需要token的,但是登录的接口不需要,此时我们在请求时就需要拦截,给除了登录接口之外的其他接口加上token。
参考官网的写法http://axios-js.com/zh-cn/docs/index.html#%E6%8B%A6%E6%88%AA%E5%99%A8
例如,我们使用的restful风格的接口,我们需要将get请求的参数拼接到URL上,那我们就可以在发送请求之前进行拼接。
// request拦截器 axiosUtil.interceptors.request.use(config => { // get请求映射params参数 if (config.method === 'get' && config.params) { let url = config.url + '?'; for (const propName of Object.keys(config.params)) { const value = config.params[propName]; const part = encodeURIComponent(propName) + '=' if (value !== null && typeof (value) !== "undefined") { if (typeof value === 'object') { for (const key of Object.keys(value)) { let params = propName + '[' + key + ']'; const subPart = encodeURIComponent(params) + '=' url += subPart + encodeURIComponent(value[key]) + "&"; } } else { url += part + encodeURIComponent(value) + "&"; } } } url = url.slice(0, -1); config.params = {}; config.url = url; } return config }, error => { console.log(error) Promise.reject(error) })
在接收到请求之后,抽离出共同的方法。
例如: 接口400怎么办,接口500怎么办!
又例如 :接收到的数据怎么办!
axiosUtil.interceptors.response.use(async res => { // 未设置状态码则默认成功状态 const code = res.data.code || 200; // 获取错误信息 const msg = res.data.msg if (code === 500) { ElMessage ({ message: msg, type: 'error' }) return Promise.reject(new Error(msg)) } else if (code = 401) { // TODO console.log("重新登录,重定向登录页面") return Promise.reject('error') } else if (code !== 200) { ElNotification .error({ title: msg }) return Promise.reject('error') } else { return res.data } }, error => { console.log('err' + error) let { message } = error; if (message === "Network Error") { message = "后端接口连接异常"; } else if (message.includes("timeout")) { message = "系统接口请求超时"; } else if (message.includes("Request failed with status code")) { message = "系统接口" + message.substr(message.length - 3) + "异常"; } ElMessage ({ message: message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } )
对于同一个模块的请求我们通常是放在封装在一个文件夹里。例如这里的测试,我会新建src\api\test.js
文件。
在这个文件里,编写涉及到测试的增删改查接口。
import axiosUtil from '../utils/axiosUtil.js'
class TestApi{
create(data){
console.log(data)
return axiosUtil.get('/test')
}
delete(data){
// 方法体内
}
}
export default new TestApi();
在src/App.vue
我们重写reqTest方法。
import TestApi from './api/test'
const reqTest = () => {
TestApi.create().then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
不启动后端,直接在前后发送请求,10000毫秒之后会弹出后端接口连接异常的消息
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。