目录
- 一、创建request.js文件
- 二、创建axios实例
- 三、创建请求、响应拦截器
- 四、使用 request.js,测试接口:https://api.uomg.com/api/rand.qinghua
- 1、调取接口代码书写
- 2、注意(跨域问题)
axios 的二次封装有三个要点:
- 创建 axios 实例,axios.create()
- 创建请求拦截器,interceptors.request.use()
- 创建响应拦截器,interceptors.response.use()
一、创建request.js文件
安装 axios 插件,指令: npm i axios
。
在 src/utils
目录下创建 request.js 文件,并引入 axios。
import axios from "axios"
二、创建axios实例
import axios from "axios"
console.log(import.meta);
// 创建axios实例
const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_API, // 设置默认的 API 地址
timeout: 5000, // 设置请求超时时间
headers: { 'systemType': 'IOS' } // 设置请求header,可以自定义属性
})
export default instance;
import.meta 是个什么东西?
import.meta 是一个 ES 模块(ESM)特性,它提供了有关当前模块的元数据。在 Vue 3 中,import.meta 可以用于访问当前 Vue 应用程序实例的上下文信息,如应用程序的基本 URL、环境变量等。
Vite 官网也说过:Vite 在一个特殊的 import.meta.env 对象上暴露环境变量。
三、创建请求、响应拦截器
在 src/utils
中创建 token 操作文件 auth.js。
const tokenKey = 'vite_token'; // 自定义tokenKey
// 获取token
export function getToken() {
return sessionStorage.getItem(tokenKey);
}
// 设置token
export function setToken(token) {
return sessionStorage.setItem(tokenKey, token);
}
// 删除token
export function removeToken() {
return sessionStorage.clear();
}
拦截器代码逻辑(完整代码):
import axios from "axios"
import { getToken } from "./auth";
import { ElMessage } from 'element-plus';
console.log(import.meta);
// 创建axios实例
const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_API, // 设置默认的 API 地址,url = baseURL + url(使用proxy代理时此处可不写)
timeout: 5000, // 设置请求超时时间
headers: { 'systemType': 'IOS' } // 设置请求header,可以自定义属性
})
// 请求拦截器
instance.interceptors.request.use(
// 请求配置(全局),一般在登录时后端返回token,此处设置token后,前端每次调取接口都会携带token
(config) => {
const token = getToken();
if (token) {
config.headers.token = token;
}
return config;
},
// 请求错误
(error) => {
return Promise.reject(error)
}
)
// 响应拦截器
instance.interceptors.response.use(
// 响应数据,2xx 范围内的状态码都会触发该函数。
(response) => {
const { status, data } = response;
if (status === 200) {
const { code, message } = data;
// 根据后端返回的自定义状态码 code 进行错误信息提示(根据具体需求确定是否需要书写)
switch (code) {
case 1001:
ElMessage({ message: '登录信息已过期,请重新登录!', type: 'error' })
return Promise.reject(data);
case 1002:
ElMessage({ message: '当前账号已在其它端登录,请重试!', type: 'error' })
return Promise.reject(data);
case 1003:
ElMessage({ message: message || '未知错误', type: 'error' })
return Promise.reject(data);
default:
return data;
}
}
},
// 响应错误,超出 2xx 范围的状态码都会触发该函数。
(error) => {
if (error.response) {
// 请求已发送,收到响应,但状态码非 2xx ,根据 http 状态码来判断响应错误信息
const { status, data } = error.response;
if (status === 2001) {
ElMessage({ message: '没查到对应数据!', type: 'error' })
} else if (status === 2002) {
ElMessage({ message: '服务器开小差了!', type: 'error' })
} else {
ElMessage({ message: data.message || '未知错误!', type: 'error' })
}
} else if (error.request) {
// 请求已发送,未收到响应
ElMessage({ message: error.message || '请求已发送,未收到响应信息!', type: 'error' })
} else {
// 其他错误
ElMessage({ message: error.message, type: 'error' })
}
// 若简写,上面代码可省略,只写此一行
return Promise.reject(error);
}
)
export default instance;
四、使用 request.js,测试接口:https://api.uomg.com/api/rand.qinghua
1、调取接口代码书写
在 src/api/about
目录下创建 index.js 文件,引入request.js,创建一个请求函数。
import request from '@/utils/request';
// 获取随机搞笑语句
export function getMessage(params = {}) {
return request({
url: '/api/rand.qinghua',
method: 'POST',
data: params
})
}
在 src/pages/about/index.vue
组件中使用:
<template>
<div class="about">
<h3>This is About page!</h3>
<el-button type="default" @click="handleClick">切换内容</el-button>
<h4>{{ message }}</h4>
</div>
</template>
<script setup>
import { getMessage } from '@/api/about'
const message = ref("")
onMounted(() => {
handleClick();
})
function handleClick() {
getMessage().then(res => {
const { content } = res;
message.value = content;
})
}
</script>
<style lang="less" scoped>
.about {
h3 {
color: grey;
}
}
</style>
需要修改 .env.development 文件:
## 开发环境
VITE_MODE='development'
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
VITE_BASE_API = 'https://api.uomg.com/'
因为 about 组件中使用了 Element Plus UI 组件库,所以还得安装一下:npm i element-plus
,然后在 main.js 文件中全局引入:
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './style.css'
import '@style/index.scss'
import '@style/index.less'
import App from './App.vue'
import router from "@/router"
const app = createApp(App)
app.use(router)
app.use(ElementPlus)
app.mount('#app')
如果想要按需引入 Element Plus 组件,首先你需要安装 unplugin-vue-components
和 unplugin-auto-import
这两款插件。详情请参考:https://element-plus.org/zh-CN/guide/quickstart.html
2、注意(跨域问题)
因为测试的 API 地址协议为 https,而本地使用的是 http,所以会出现跨域问题:
这时候就必须使用代理 proxy了。而要使用 proxy 代理,则 request.js 文件中的 baseURL 配置项就不再需要了。
此处说明一下:
- 如果 axios 的 baseURL 配置的是绝对路径,例如
'http://192.168.1.32:8000/'
,axios 会直接发送请求而不经过 server.proxy。 - 如果 axios 的 baseURL 配置的是相对路径,例如
'/api'
,则可以正常使用 server.proxy 进行请求转发,不会存在跨域问题。
此处若配置 baseURL,则路径地址变成了 https://api.uomg.com/api/rand.qinghua
这样的绝对路径;而不配置 baseURL ,则为相对路径 /api/rand.qinghua
。proxy匹配到了 '/api'
,会使用配置的 target 选项拼接成完整路径:target + '/api/rand.qinghua'
进行请求。
当然,此处的配置还有其他方式,不做赘述。
const instance = axios.create({
baseURL: '', // 设置默认的 API 地址,url = baseURL + url
timeout: 5000, // 设置请求超时时间
headers: { 'systemType': 'IOS' } // 设置请求header,可以自定义属性
})
vite.config.js 文件中的 proxy 配置也需要修改:
proxy: {
'/api': {
target: env.VITE_BASE_API,
changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ''), // 此行注释
},
}
因为 '/api'
是地址 https://api.uomg.com/api/rand.qinghua
中的成员,所以 rewrite 配置项不需要再将 '/api'
重写为 ''
。
看效果: