一、为什么说Axios是Vue开发的“灵魂伴侣”?
各位前端er,不知道你们有没有这样的经历:用原生fetch写请求时,感觉自己像个“网络乞丐”,每个请求都要重复写一堆配置,错误处理更是让人头大。直到遇见了Axios——这货简直就是前端界的“瑞士军刀”!
先来说说Axios凭什么能成为Vue官方推荐的请求库:
1. 开箱即用的爽感
// 不用Axios时(痛苦面具)
fetch('/api/user', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token
}
})
.then(response => {
if (!response.ok) throw new Error('Network error');
return response.json();
})
// 用了Axios后(真香!)
axios.get('/api/user', {
headers: { 'Authorization': 'Bearer ' + token }
})
2. 浏览器兼容性拉满
IE11?抱歉,fetch真的不熟。Axios却能让你的应用在各类浏览器里畅通无阻,这就是底气!
3. 进度监控超能力
上传下载进度条?Axios轻松搞定,用户体验直接拉满。
二、Axios基础配置:从“能用”到“好用”
2.1 安装与引入的“正确姿势”
npm install axios
在Vue项目中,我强烈推荐创建单独的请求模块:
// src/utils/request.js
import axios from 'axios';
// 创建实例 - 这是专业项目的标配
const request = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL || '/api',
timeout: 10000, // 10秒超时,防止用户变成“等等党”
headers: {
'Content-Type': 'application/json;charset=UTF-8'
}
});
export default request;
2.2 核心配置项详解
// 这些配置项记牢,面试都能多拿2k!
const config = {
// 请求的服务器URL(必填)
url: '/user',
// 请求方法,默认get(选填)
method: 'get', // 可选:get, post, put, delete...
// 基础URL路径(智能拼接)
baseURL: 'https://api.example.com',
// 自定义请求头(装X必备)
headers: { 'X-Custom-Header': 'foobar' },
// URL参数(GET请求专用)
params: { id: 12345 },
// 请求体数据(POST/PUT专用)
data: { name: '张三', age: 18 },
// 超时时间(单位毫秒)
timeout: 5000,
// 响应数据类型
responseType: 'json', // 可选:arraybuffer, blob, document, json, text, stream
}
三、拦截器:Axios的“魔法道具”
拦截器就是Axios的灵魂所在,用好它能让你的代码优雅度提升200%!
3.1 请求拦截器:给每个请求“化个妆”
// 统一添加token,告别重复代码
request.interceptors.request.use(
(config) => {
// 在发送请求前做些羞羞的事
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
// 显示loading动画
showLoading();
return config;
},
(error) => {
// 对请求错误做些什么(比如:请求配置有问题)
hideLoading();
return Promise.reject(error);
}
);
3.2 响应拦截器:统一处理错误和数据
request.interceptors.response.use(
(response) => {
// 2xx范围内的状态码都会触发该函数
hideLoading();
// 如果后端返回的数据结构是 { code: 200, data: {}, message: 'success' }
const { code, data, message } = response.data;
if (code === 200) {
return data; // 直接返回真正的数据,爽!
} else {
// 业务逻辑错误
ElMessage.error(message || '系统异常');
return Promise.reject(new Error(message || 'Error'));
}
},
(error) => {
// 超出2xx范围的状态码都会触发该函数
hideLoading();
// 根据HTTP状态码做不同的错误处理
if (error.response?.status === 401) {
ElMessage.error('登录已过期,请重新登录');
router.push('/login');
} else if (error.response?.status === 403) {
ElMessage.error('没有权限访问该资源');
} else if (error.response?.status === 500) {
ElMessage.error('服务器开小差了,请稍后重试');
} else if (error.code === 'ECONNABORTED') {
ElMessage.error('请求超时,请检查网络连接');
} else {
ElMessage.error('网络异常,请稍后重试');
}
return Promise.reject(error);
}
);
四、实战:用户管理系统完整示例
下面我们来搞个真实的用户管理系统,看看Axios在实战中怎么用:
4.1 API模块化封装
// src/api/user.js
import request from '@/utils/request';
// 用户相关的所有API请求
export const userAPI = {
// 获取用户列表
getUsers(params) {
return request.get('/users', { params });
},
// 获取用户详情
getUserDetail(id) {
return request.get(`/users/${id}`);
},
// 创建用户
createUser(data) {
return request.post('/users', data);
},
// 更新用户
updateUser(id, data) {
return request.put(`/users/${id}`, data);
},
// 删除用户
deleteUser(id) {
return request.delete(`/users/${id}`);
},
// 批量删除用户
batchDeleteUsers(ids) {
return request.post('/users/batch-delete', { ids });
}
};
4.2 在Vue组件中使用
<template>
<div class="user-management">
<!-- 用户列表 -->
<el-table :data="userList" v-loading="loading">
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button @click="handleEdit(scope.row)">编辑</el-button>
<el-button type="danger" @click="handleDelete(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 添加用户表单 -->
<el-dialog v-model="dialogVisible" title="添加用户">
<el-form :model="userForm" :rules="rules" ref="formRef">
<el-form-item label="姓名" prop="name">
<el-input v-model="userForm.name" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input v-model="userForm.email" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { userAPI } from '@/api/user';
const loading = ref(false);
const dialogVisible = ref(false);
const userList = ref([]);
const formRef = ref();
const userForm = reactive({
name: '',
email: ''
});
const rules = {
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
email: [
{ required: true, message: '请输入邮箱', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
]
};
// 获取用户列表
const fetchUsers = async () => {
try {
loading.value = true;
const data = await userAPI.getUsers({
page: 1,
pageSize: 10
});
userList.value = data.list;
} catch (error) {
console.error('获取用户列表失败:', error);
} finally {
loading.value = false;
}
};
// 添加用户
const handleSubmit = async () => {
try {
await formRef.value.validate();
await userAPI.createUser(userForm);
ElMessage.success('添加用户成功');
dialogVisible.value = false;
fetchUsers(); // 重新获取列表
} catch (error) {
// 错误已经在拦截器里统一处理了,这里不用再写ElMessage
}
};
// 删除用户
const handleDelete = async (id) => {
try {
await ElMessageBox.confirm('确定删除该用户吗?', '提示', {
type: 'warning'
});
await userAPI.deleteUser(id);
ElMessage.success('删除成功');
fetchUsers();
} catch (error) {
if (error === 'cancel') {
ElMessage.info('已取消删除');
}
}
};
onMounted(() => {
fetchUsers();
});
</script>
五、高级技巧:让你的Axios更“聪明”
5.1 取消重复请求:防止用户“手抖”
// 用于存储正在进行中的请求
const pendingRequests = new Map();
// 生成请求的key
const generateReqKey = (config) => {
return [config.method, config.url, JSON.stringify(config.params), JSON.stringify(config.data)].join('&');
};
// 添加请求到pending中
const addPendingRequest = (config) => {
const key = generateReqKey(config);
config.cancelToken = config.cancelToken || new axios.CancelToken(cancel => {
if (!pendingRequests.has(key)) {
pendingRequests.set(key, cancel);
}
});
};
// 移除请求
const removePendingRequest = (config) => {
const key = generateReqKey(config);
if (pendingRequests.has(key)) {
const cancel = pendingRequests.get(key);
cancel(key);
pendingRequests.delete(key);
}
};
// 在请求拦截器中添加
request.interceptors.request.use(config => {
removePendingRequest(config); // 检查是否存在重复请求,若存在则取消
addPendingRequest(config); // 把当前请求添加到pending中
return config;
});
// 在响应拦截器中移除
request.interceptors.response.use(response => {
removePendingRequest(response.config);
return response;
}, error => {
removePendingRequest(error.config || {});
return Promise.reject(error);
});
5.2 自动重试机制:给请求“上保险”
// 重试配置
const retryConfig = {
retries: 3, // 重试次数
retryDelay: 1000, // 重试延迟
};
const retryRequest = (config) => {
return new Promise((resolve, reject) => {
const attempt = (retryCount) => {
request(config)
.then(resolve)
.catch((error) => {
if (retryCount > 0 && shouldRetry(error)) {
setTimeout(() => {
attempt(retryCount - 1);
}, retryConfig.retryDelay);
} else {
reject(error);
}
});
};
attempt(retryConfig.retries);
});
};
const shouldRetry = (error) => {
// 只在网络错误或5xx错误时重试
return !error.response || error.response.status >= 500;
};
六、多环境配置:一套代码走天下
// .env.development
VUE_APP_API_BASE_URL=http://localhost:3000/api
VUE_APP_MODE=development
// .env.production
VUE_APP_API_BASE_URL=https://api.yourdomain.com
VUE_APP_MODE=production
// .env.test
VUE_APP_API_BASE_URL=https://test-api.yourdomain.com
VUE_APP_MODE=test
// 在axios配置中使用
const request = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL,
timeout: 10000,
});
七、常见坑点与解决方案
坑点1:POST请求变成OPTIONS
// 问题:浏览器先发OPTIONS预检请求
// 解决:后端配置CORS,或者简单请求避免预检
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded' // 简单请求
}
}
坑点2:请求超时设置不合理
// 根据不同请求类型设置不同超时时间
const getTimeout = (url) => {
if (url.includes('/upload')) return 30000; // 上传文件给30秒
if (url.includes('/export')) return 60000; // 导出数据给1分钟
return 10000; // 普通请求10秒
}
八、总结
看到这里,相信你已经从Axios的“入门小白”晋级为“配置高手”了!记住几个核心要点:
- 实例化是基础 - 别再用axios直接调用了
- 拦截器是灵魂 - 统一处理让代码更优雅
- 错误处理要全面 - 给用户更好的体验
- API要模块化 - 维护起来真香
Axios的配置就像做菜,基础的调料大家都一样,但秘制酱料才是决定味道的关键。希望本文的“秘制配方”能帮你做出更美味的“前端大餐”!
最后的忠告:别再做“CV工程师”了,把这些配置封装成你自己的请求库,下次新项目直接拿来就用,老板看了直呼内行!

被折叠的 条评论
为什么被折叠?



