Vue3 学习教程,从入门到精通,Axios 在 Vue 3 中的使用指南(37)
Axios 在 Vue 3 中的使用指南
本文档将详细介绍 Axios 在 Vue 3 中的应用,包括安装配置、基本用法、结合 Vue Router 和 Pinia 的异步数据管理、封装优化以及安全性与性能优化等内容。每个知识点都配有详细的代码示例,并提供综合性案例以帮助理解。
目录
- Axios 概述
- Axios 的安装与配置
- 发起请求与处理响应
- 在 Vue 组件中使用 Axios
- Vue 3 中的 Axios 实例
- Axios 结合 Vue Router 的异步加载数据
- Pinia 中的异步数据管理与 Axios
- Axios 公共逻辑与封装
- 创建可复用的 Axios 封装
- 处理请求的 Loading 状态
- 统一处理错误提示与日志记录
- 优化 Axios 封装与配置
- 安全性与性能优化
- 有关网络请求的安全性
- 性能优化
- 综合性案例
- 本章小结
1. Axios 概述
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它具有以下优势:
- 支持 Promise API
- 支持拦截请求和响应
- 自动转换 JSON 数据
- 支持取消请求
- 支持客户端和服务器端请求
- 浏览器兼容性良好
2. Axios 的安装与配置
安装 Axios
使用 npm 或 yarn 安装 Axios:
npm install axios
# 或者
yarn add axios
配置 Axios
在 Vue 3 项目中,通常在 src
目录下创建一个 axios
文件夹,用于存放 Axios 的配置和封装。
// src/axios/index.js
import axios from 'axios';
import { useToast } from 'vue-toastification';// 创建 Axios 实例
const instance = axios.create({baseURL: 'https://api.example.com', // 基础 URLtimeout: 10000, // 请求超时时间
});// 请求拦截器
instance.interceptors.request.use((config) => {// 在发送请求之前做些什么,例如添加认证 tokenconst token = localStorage.getItem('token');if (token) {config.headers['Authorization'] = `Bearer ${token}`;}return config;},(error) => {return Promise.reject(error);}
);// 响应拦截器
instance.interceptors.response.use((response) => {// 对响应数据做点什么return response.data;},(error) => {// 对响应错误做点什么const toast = useToast();toast.error('请求失败,请稍后重试');return Promise.reject(error);}
);export default instance;
3. 发起请求与处理响应
GET 请求
// src/axios/get.js
import axios from './index';export const getUser = (userId) => {return axios.get(`/users/${userId}`);
};
POST 请求
// src/axios/post.js
import axios from './index';export const createUser = (userData) => {return axios.post('/users', userData);
};
处理响应
// src/components/User.vue
<template><div><h1>用户信息</h1><p v-if="loading">加载中...</p><p v-else-if="error">发生错误: {{ error }}</p><div v-else><p>姓名: {{ user.name }}</p><p>邮箱: {{ user.email }}</p></div></div>
</template><script>
import { ref } from 'vue';
import { getUser } from '../axios/get';export default {name: 'User',setup() {const user = ref(null);const loading = ref(false);const error = ref(null);const fetchUser = async (id) => {loading.value = true;error.value = null;try {const response = await getUser(id);user.value = response;} catch (err) {error.value = err.message;} finally {loading.value = false;}};fetchUser(1);return {user,loading,error,};},
};
</script>
4. 在 Vue 组件中使用 Axios
在 Vue 组件中,可以通过 setup
函数或 methods
使用 Axios。
使用 setup
函数
// src/components/PostList.vue
<template><div><h1>帖子列表</h1><ul><li v-for="post in posts" :key="post.id">{{ post.title }}</li></ul></div>
</template><script>
import { ref, onMounted } from 'vue';
import { getPosts } from '../axios/get';export default {name: 'PostList',setup() {const posts = ref([]);const fetchPosts = async () => {const response = await getPosts();posts.value = response;};onMounted(() => {fetchPosts();});return {posts,};},
};
</script>
使用 methods
// src/components/Login.vue
<template><div><h1>登录</h1><form @submit.prevent="login"><input v-model="username" placeholder="用户名" /><input v-model="password" type="password" placeholder="密码" /><button type="submit">登录</button></form><p v-if="error">{{ error }}</p></div>
</template><script>
import { ref } from 'vue';
import { loginUser } from '../axios/post';export default {name: 'Login',setup() {const username = ref('');const password = ref('');const error = ref(null);const login = async () => {try {const response = await loginUser({ username: username.value, password: password.value });// 处理登录成功逻辑,例如保存 tokenconsole.log('登录成功', response);} catch (err) {error.value = '登录失败,请检查用户名和密码';}};return {username,password,login,error,};},
};
</script>
5. Vue 3 中的 Axios 实例
在 Vue 3 中,可以通过 app.config.globalProperties
将 Axios 实例挂载到全局属性中,方便在组件中直接使用。
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import axios from './axios/index';const app = createApp(App);// 将 Axios 实例挂载到全局属性
app.config.globalProperties.$axios = axios;app.mount('#app');
在组件中使用:
// src/components/Example.vue
<template><div><h1>全局 Axios 实例示例</h1><button @click="makeRequest">发起请求</button><p v-if="loading">加载中...</p><p v-else-if="error">错误: {{ error }}</p><p v-else>响应数据: {{ data }}</p></div>
</template><script>
import { ref, onMounted } from 'vue';export default {name: 'Example',setup() {const data = ref(null);const loading = ref(false);const error = ref(null);const makeRequest = async () => {loading.value = true;error.value = null;try {const response = await this.$axios.get('/example-endpoint');data.value = response;} catch (err) {error.value = err.message;} finally {loading.value = false;}};onMounted(() => {makeRequest();});return {data,loading,error,makeRequest,};},
};
</script>
6. Axios 结合 Vue Router 的异步加载数据
在 Vue Router 中,可以使用 async
函数来异步加载数据。
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import axios from '../axios/index';
import Home from '../components/Home.vue';
import User from '../components/User.vue';const routes = [{path: '/',name: 'Home',component: Home,async beforeEnter() {const response = await axios.get('/home-data');// 可以在这里进行数据预处理return true;},},{path: '/user/:id',name: 'User',component: User,async beforeEnter(to) {const userId = to.params.id;const response = await axios.get(`/users/${userId}`);// 可以在这里进行数据预处理return true;},},
];const router = createRouter({history: createWebHistory(),routes,
});export default router;
7. Pinia 中的异步数据管理与 Axios
在 Pinia 中,可以使用 actions
来管理异步数据。
// src/stores/userStore.js
import { defineStore } from 'pinia';
import axios from '../axios/index';export const useUserStore = defineStore('user', {state: () => ({users: [],loading: false,error: null,}),actions: {async fetchUsers() {this.loading = true;this.error = null;try {const response = await axios.get('/users');this.users = response;} catch (err) {this.error = err.message;} finally {this.loading = false;}},},
});
在组件中使用:
// src/components/UserList.vue
<template><div><h1>用户列表</h1><p v-if="userStore.loading">加载中...</p><p v-else-if="userStore.error">错误: {{ userStore.error }}</p><ul><li v-for="user in userStore.users" :key="user.id">{{ user.name }}</li></ul></div>
</template><script>
import { useUserStore } from '../stores/userStore';export default {name: 'UserList',setup() {const userStore = useUserStore();onMounted(() => {userStore.fetchUsers();});return {userStore,};},
};
</script>
8. Axios 公共逻辑与封装
8.1 创建可复用的 Axios 封装
// src/axios/instance.js
import axios from 'axios';
import { useToast } from 'vue-toastification';const instance = axios.create({baseURL: 'https://api.example.com',timeout: 10000,
});const toast = useToast();instance.interceptors.request.use((config) => {const token = localStorage.getItem('token');if (token) {config.headers['Authorization'] = `Bearer ${token}`;}return config;},(error) => {return Promise.reject(error);}
);instance.interceptors.response.use((response) => {return response.data;},(error) => {toast.error('请求失败,请稍后重试');return Promise.reject(error);}
);export default instance;
8.2 处理请求的 Loading 状态
// src/axios/loading.js
import axios from './instance';
import { ref } from 'vue';export const useAxiosWithLoading = () => {const loading = ref(false);const request = async (config) => {loading.value = true;try {const response = await axios(config);return response;} finally {loading.value = false;}};return {loading,request,};
};
8.3 统一处理错误提示与日志记录
// src/axios/errorHandler.js
import { useToast } from 'vue-toastification';
import axios from './instance';const toast = useToast();axios.interceptors.response.use((response) => {return response;},(error) => {// 记录错误日志console.error('Axios 错误:', error);// 显示错误提示toast.error('请求失败,请稍后重试');return Promise.reject(error);}
);
8.4 优化 Axios 封装与配置
// src/axios/index.js
import axios from './instance';
import { useAxiosWithLoading } from './loading';
import './errorHandler';const { loading, request } = useAxiosWithLoading();export { axios, loading, request };
9. 安全性与性能优化
9.1 有关网络请求的安全性
- 认证与授权:使用 JWT 或 OAuth 进行认证,并在请求头中携带 token。
- 数据加密:使用 HTTPS 协议,确保数据在传输过程中被加密。
- 防止 CSRF:使用 CSRF tokens 或双重 cookie 验证。
- 输入验证:对用户输入进行严格验证,防止 SQL 注入和 XSS 攻击。
9.2 性能优化
- 请求缓存:使用浏览器缓存或 Axios 缓存插件,减少不必要的请求。
- 请求合并:将多个请求合并为一个批量请求,减少网络开销。
- 压缩数据:使用 gzip 等压缩技术,减少传输数据量。
- 懒加载:按需加载数据,避免一次性加载过多数据。
10. 综合性案例
综合案例:用户登录与用户列表展示
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import axios from './axios/index';
import { createPinia } from 'pinia';const app = createApp(App);
const pinia = createPinia();app.use(pinia);
app.use(router);
app.config.globalProperties.$axios = axios;
app.mount('#app');
// src/stores/userStore.js
import { defineStore } from 'pinia';
import { useAxiosWithLoading } from '../axios/loading';export const useUserStore = defineStore('user', {state: () => ({users: [],currentUser: null,loading: false,error: null,}),actions: {async login(username, password) {this.loading = true;this.error = null;try {const response = await axios.post('/login', { username, password });this.currentUser = response;localStorage.setItem('token', response.token);} catch (err) {this.error = '登录失败,请检查用户名和密码';} finally {this.loading = false;}},async fetchUsers() {this.loading = true;this.error = null;try {const response = await axios.get('/users');this.users = response;} catch (err) {this.error = '获取用户列表失败';} finally {this.loading = false;}},},
});
// src/components/Login.vue
<template><div><h1>登录</h1><form @submit.prevent="login"><input v-model="username" placeholder="用户名" /><input v-model="password" type="password" placeholder="密码" /><button type="submit">登录</button></form><p v-if="error">{{ error }}</p><p v-if="loading">加载中...</p></div>
</template><script>
import { ref } from 'vue';
import { useUserStore } from '../stores/userStore';export default {name: 'Login',setup() {const username = ref('');const password = ref('');const userStore = useUserStore();const login = async () => {await userStore.login(username.value, password.value);};return {username,password,login,error: userStore.error,loading: userStore.loading,};},
};
// src/components/UserList.vue
<template><div><h1>用户列表</h1><p v-if="userStore.loading">加载中...</p><p v-else-if="userStore.error">{{ userStore.error }}</p><ul><li v-for="user in userStore.users" :key="user.id">{{ user.name }}</li></ul></div>
</template><script>
import { useUserStore } from '../stores/userStore';export default {name: 'UserList',setup() {const userStore = useUserStore();onMounted(() => {userStore.fetchUsers();});return {userStore,};},
};
11. 本章小结
本文档详细介绍了 Axios 在 Vue 3 中的应用,包括安装配置、基本用法、结合 Vue Router 和 Pinia 的异步数据管理、封装优化以及安全性与性能优化等内容。通过这些知识,开发者可以更高效地在 Vue 3 项目中使用 Axios 进行网络请求和数据管理。