模式切换
Axios
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。
安装 Axios
首先需要在项目中安装 Axios:
bash
npm install axios
# 或
yarn add axios
基本使用
直接在组件中使用
javascript
import axios from 'axios';
export default {
methods: {
fetchData() {
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error fetching data:', error);
});
},
postData() {
axios.post('https://api.example.com/data', {
key: 'value'
})
.then(response => {
console.log(response.data);
});
}
}
}
使用 async/await 语法
javascript
export default {
methods: {
async fetchData() {
try {
const response = await axios.get('https://api.example.com/data');
console.log(response.data);
} catch (error) {
console.error('Error fetching data:', error);
}
}
}
}
创建 Axios 实例
为了更好的管理和配置,通常我们会创建一个自定义的 Axios 实例:
javascript
// src/utils/axios.js
import axios from 'axios';
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
headers: {
'Content-Type': 'application/json',
}
});
export default api;
然后在组件中使用:
javascript
import api from '@/utils/axios';
export default {
methods: {
async fetchData() {
try {
const response = await api.get('/data');
console.log(response.data);
} catch (error) {
console.error(error);
}
}
}
}
全局配置
可以在 main.js 中将 Axios 配置为全局属性:
javascript
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import axios from 'axios';
const app = createApp(App);
// 配置全局axios
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// 添加到Vue原型链(可选,Vue3推荐使用provide/inject)
app.config.globalProperties.$http = axios;
app.mount('#app');
然后在组件中使用:
javascript
export default {
methods: {
async fetchData() {
try {
const response = await this.$http.get('/data');
console.log(response.data);
} catch (error) {
console.error(error);
}
}
}
}
请求和响应拦截器
拦截器可以用于在请求发送前或响应返回后添加统一处理逻辑:
javascript
// 请求拦截器
axios.interceptors.request.use(
config => {
// 在发送请求前做些什么
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 响应拦截器
axios.interceptors.response.use(
response => {
// 对响应数据做点什么
return response.data; // 通常我们只需要data部分
},
error => {
// 对响应错误做点什么
if (error.response.status === 401) {
// 处理未授权
router.push('/login');
}
return Promise.reject(error);
}
);
组合式 API 中使用 Axios
在 Vue 3 的组合式 API 中,可以这样使用 Axios:
javascript
// src/composables/useApi.js
import { ref } from 'vue';
import api from '@/utils/axios';
export function useApi() {
const data = ref(null);
const error = ref(null);
const loading = ref(false);
const fetchData = async (url) => {
loading.value = true;
try {
const response = await api.get(url);
data.value = response.data;
} catch (err) {
error.value = err;
} finally {
loading.value = false;
}
};
return { data, error, loading, fetchData };
}
在组件中使用:
vue
<template>
<div>
<button @click="getData">获取数据</button>
<div v-if="loading">加载中...</div>
<div v-else-if="error">错误: {{ error.message }}</div>
<div v-else>{{ data }}</div>
</div>
</template>
<script>
import { useApi } from '@/composables/useApi';
export default {
setup() {
const { data, error, loading, fetchData } = useApi();
const getData = () => {
fetchData('/posts');
};
return { data, error, loading, getData };
}
};
</script>
取消请求
Axios 支持取消请求,这在用户快速切换页面时很有用:
javascript
import axios from 'axios';
const CancelToken = axios.CancelToken;
let cancel;
export default {
methods: {
fetchData() {
// 如果已有请求在进行,先取消
if (cancel) cancel();
axios.get('/data', {
cancelToken: new CancelToken(function executor(c) {
cancel = c;
})
})
.then(response => {
console.log(response.data);
})
.catch(thrown => {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 处理错误
}
});
}
}
}
常见配置选项
Axios 支持许多配置选项,以下是一些常用的:
javascript
axios({
method: 'get', // 默认
url: '/user',
baseURL: 'https://api.example.com',
headers: { 'X-Requested-With': 'XMLHttpRequest' },
params: { ID: 12345 }, // URL 参数
data: { firstName: 'Fred' }, // 请求体数据 (POST/PUT/PATCH)
timeout: 1000, // 超时时间
responseType: 'json', // 默认
withCredentials: false, // 跨域请求时是否需要使用凭证
auth: { username: 'janedoe', password: 's00pers3cret' }, // HTTP基本认证
// 其他配置...
});
最佳实践
- 封装 API 模块:将 API 请求封装到单独的模块中,而不是分散在各个组件
- 统一错误处理:使用拦截器统一处理错误
- 环境变量:将 API 基础 URL 放在环境变量中
- 类型安全:在 TypeScript 项目中为 API 响应定义接口
- 取消重复请求:在路由切换时取消未完成的请求
示例 API 模块封装:
javascript
// src/api/user.js
import api from '@/utils/axios';
export default {
getUsers() {
return api.get('/users');
},
getUser(id) {
return api.get(`/users/${id}`);
},
createUser(user) {
return api.post('/users', user);
},
updateUser(id, user) {
return api.put(`/users/${id}`, user);
},
deleteUser(id) {
return api.delete(`/users/${id}`);
}
};
然后在组件中导入使用:
javascript
import userApi from '@/api/user';
export default {
methods: {
async loadUsers() {
try {
const response = await userApi.getUsers();
this.users = response.data;
} catch (error) {
console.error(error);
}
}
}
}