Vue3集成Axios实战指南

在现代前端开发中,与后端 API 进行数据交互是必不可少的环节。Vue3 作为当前最流行的前端框架之一,虽然本身不包含 HTTP 请求功能,但我们可以通过集成 Axios 来实现强大的网络请求能力。本文将从零开始,详细介绍如何在 Vue3 项目中使用 Axios,涵盖基础用法到高级技巧的完整内容

一、Axios简介:为什么选择它

1.1 什么是Axios

Axios 是一个基于 Promise 的 HTTP 客户端,可用于浏览器和 Node.js 环境。它本质上是对原生 XMLHttpRequest 的封装,但采用了 Promise 的实现方式,符合最新的 ES 规范

1.2 Axios的主要特点

支持浏览器和 Node.js:一套代码可以在前后端通用

Promise API:支持 async / await 语法,代码更简洁

拦截请求和响应:可以在请求发送前和响应返回后进行统一处理

自动转换 JSON 数据:无需手动解析 JSON 响应

客户端防止 XSRF:提供了 XSRF 保护机制

请求取消:支持取消正在进行的请求

自动转换请求和响应数据:简化数据处理流程

1.3 为什么在 Vue3 中选择 Axios

Vue 本身专注于视图层,不包含 HTTP 请求功能。Vue 官方在 2.0 版本后,不再维护 vue-resource,并推荐使用 Axios。选择 Axios 的主要原因包括:

① 解耦性好:Axios 与 Vue 没有直接耦合,可以轻松地在任何项目中使用

② 功能强大:丰富的 API 和强大的功能(如拦截器、实例创建)满足复杂项目需求

③ 社区活跃:生态完善,遇到问题容易找到解决方案

④ TypeScript 支持:提供完整的 TypeScript 类型定义

二、Axios 安装与基础配置

2.1 安装 Axios

在 Vue3 项目中安装 Axios 非常简单:

npm install axios
# 或
yarn add axios

对于简单的非工程化页面,也可以通过 CDN 引入:

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

2.2 在 Vue3 中引入 Axios 的三种方式

方式一:局部引入

此方式适合简单项目,在需要使用的组件中直接引入:

import axios from 'axios';

export default {
  setup() {
    const fetchData = async () => {
      try {
        const response = await axios.get('/api/data');
        console.log(response.data);
      } catch (error) {
        console.error(error);
      }
    };
    
    return { fetchData };
  }
};

方式二:全局挂载

在 main.js 中将 Axios 挂载到 Vue 实例原型上:

import { createApp } from 'vue';
import axios from 'axios';
import App from './App.vue';

const app = createApp(App);
app.config.globalProperties.$axios = axios;
app.mount('#app');

此方法不推荐使用,理由:

① 污染全局命名空间        ② 在Composition API 的setup 函数中访问不便

③ 不利于类型检查

方式三:封装为模块

推荐使用此方式,创建专门的模块来封装 Axios,这是最佳实践:

// src/utils/request.js
import axios from 'axios';

// 创建Axios实例
const service = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
  timeout: 5000, // 请求超时时间
  headers: {
    'Content-Type': 'application/json'
  }
});

export default service;

在组件中使用:

import request from '@/utils/request';

export default {
  setup() {
    const fetchData = async () => {
      try {
        const response = await request.get('/posts');
        console.log(response.data);
      } catch (error) {
        console.error(error);
      }
    };
    
    return { fetchData };
  }
};

2.3 基本配置选项详解

Axios 提供了丰富的配置选项,常用的包括:

const config = {
  url: '/user', // 请求的服务器URL
  method: 'get', // 请求方法,默认为'get'
  baseURL: 'https://api.example.com', // 基础URL
  headers: { 'X-Requested-With': 'XMLHttpRequest' }, // 请求头
  params: { ID: 12345 }, // URL查询参数
  data: { firstName: 'Fred' }, // 请求体数据
  timeout: 1000, // 请求超时时间(毫秒)
  responseType: 'json', // 响应数据类型
  maxRedirects: 5, // 最大重定向次数
  withCredentials: false, // 是否携带cookie
};

三、Axios基本用法

3.1 常用请求方法

Axios 为所有 HTTP 请求方法都提供了别名:

// GET请求
axios.get('/user?ID=12345')
  .then(response => console.log(response))
  .catch(error => console.error(error));

// 带参数的GET请求
axios.get('/user', {
  params: {
    ID: 12345
  }
});

// POST请求
axios.post('/user', {
  firstName: 'Fred',
  lastName: 'Flintstone'
});

// PUT请求
axios.put('/user/12345', {
  firstName: 'Fred',
  lastName: 'Flintstone'
});

// DELETE请求
axios.delete('/user/12345');

// PATCH请求
axios.patch('/user/12345', {
  firstName: 'Fred'
});

3.2 使用 async/await 语法

现代 JavaScript 推荐使用 async/await 语法,代码更简洁易读:

export default {
  setup() {
    const fetchUser = async (userId) => {
      try {
        const response = await axios.get(`/users/${userId}`);
        console.log('用户数据:', response.data);
        return response.data;
      } catch (error) {
        console.error('获取用户数据失败:', error);
        throw error;
      }
    };
    
    return { fetchUser };
  }
};

3.3 响应数据结构

Axios 的响应对象包含以下属性:

{
  data: {}, // 服务器返回的响应数据
  status: 200, // HTTP状态码
  statusText: 'OK', // HTTP状态消息
  headers: {}, // 响应头
  config: {}, // 请求配置对象
  request: {} // 原始请求对象
}

3.4 Vue3 组件中的实际应用

下面是一个完整的 Vue3 组件示例,展示如何使用 Axios 获取和展示数据:

<template>
  <div class="user-profile">
    <div v-if="loading" class="loading">加载中...</div>
    <div v-else-if="error" class="error">{{ error }}</div>
    <div v-else-if="user" class="profile">
      <h2>{{ user.name }}</h2>
      <p>邮箱: {{ user.email }}</p>
      <p>电话: {{ user.phone }}</p>
    </div>
    
    <button @click="fetchUserData">获取用户数据</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import axios from 'axios';

const user = ref(null);
const loading = ref(false);
const error = ref(null);

const fetchUserData = async () => {
  loading.value = true;
  error.value = null;
  
  try {
    const response = await axios.get('https://jsonplaceholder.typicode.com/users/1');
    user.value = response.data;
  } catch (err) {
    error.value = '获取用户数据失败,请稍后重试';
    console.error('请求失败:', err);
  } finally {
    loading.value = false;
  }
};
</script>

<style scoped>
.user-profile {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.loading, .error {
  padding: 20px;
  text-align: center;
  color: #666;
}

.error {
  color: #ff4444;
}

.profile {
  background: #f5f5f5;
  padding: 20px;
  border-radius: 8px;
}

button {
  margin-top: 20px;
  padding: 10px 20px;
  background: #42b983;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background: #369870;
}
</style>

四、Axios 进阶应用

4.1 Axios 实例创建与管理

在大型项目中,通常需要与多个后端服务交互,此时创建多个 Axios 实例是最佳实践

创建多个实例:

// src/utils/api/postService.js
import axios from 'axios';

export const postService = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/posts',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json'
  }
});

// src/utils/api/userService.js
import axios from 'axios';

export const userService = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com/users',
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json'
  }
});

配置优先级:Axios 的配置有三个层级,优先级从高到低:

① 请求时配置:只对当前请求有效

② 实例配置:对该实例的所有请求有效

③ 全局配置:对所有请求有效

// 全局配置
axios.defaults.baseURL = 'https://api.example.com';

// 实例配置
const service = axios.create({
  baseURL: 'https://api.service.com'
});

// 请求时配置
service.get('/data', {
  timeout: 1000
});

4.2 拦截器:请求与响应的统一处理

拦截器是 Axios 最强大的功能之一,允许你在请求发送前和响应返回后进行统一处理

请求拦截器

常用于添加认证 token、显示 loading 状态等:

// src/utils/request.js
import axios from 'axios';

const service = axios.create({
  baseURL: 'https://jsonplaceholder.typicode.com',
  timeout: 5000
});

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    // 在发送请求之前做些什么
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    
    // 显示loading
    store.commit('showLoading');
    
    return config;
  },
  (error) => {
    // 对请求错误做些什么
    store.commit('hideLoading');
    return Promise.reject(error);
  }
);

响应拦截器

常用于统一错误处理、数据格式化等:

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // 对响应数据做点什么
    store.commit('hideLoading');
    
    // 简化数据层级,直接返回data
    return response.data;
  },
  (error) => {
    // 对响应错误做点什么
    store.commit('hideLoading');
    
    // 统一错误处理
    if (error.response) {
      switch (error.response.status) {
        case 401:
          // 未授权,跳转到登录页
          router.push('/login');
          break;
        case 404:
          console.error('请求的资源不存在');
          break;
        case 500:
          console.error('服务器内部错误');
          break;
        default:
          console.error('请求失败:', error.response.data);
      }
    } else if (error.request) {
      console.error('网络连接失败');
    }
    
    return Promise.reject(error);
  }
);

export default service;

4.3 错误处理最佳实践

常见错误类型

const fetchData = async () => {
  try {
    const response = await service.get('/data');
    return response;
  } catch (error) {
    if (error.response) {
      // 请求已发出,服务器返回状态码不在2xx范围内
      console.log('响应错误:', error.response.data);
      console.log('状态码:', error.response.status);
      console.log('响应头:', error.response.headers);
    } else if (error.request) {
      // 请求已发出,但没有收到响应
      console.log('请求错误:', error.request);
    } else {
      // 请求配置发生错误
      console.log('配置错误:', error.message);
    }
    console.log('请求配置:', error.config);
    
    throw error;
  }
};

Axios 支持取消正在进行的请求:

import { ref } from 'vue';
import axios from 'axios';

export default {
  setup() {
    const cancelTokenSource = ref(null);
    
    const fetchData = async () => {
      // 取消之前的请求(如果存在)
      if (cancelTokenSource.value) {
        cancelTokenSource.value.cancel('请求已取消');
      }
      
      cancelTokenSource.value = axios.CancelToken.source();
      
      try {
        const response = await axios.get('/data', {
          cancelToken: cancelTokenSource.value.token
        });
        return response.data;
      } catch (error) {
        if (axios.isCancel(error)) {
          console.log('请求被取消:', error.message);
        } else {
          console.error('请求失败:', error);
        }
      }
    };
    
    const cancelRequest = () => {
      if (cancelTokenSource.value) {
        cancelTokenSource.value.cancel('用户主动取消请求');
      }
    };
    
    return { fetchData, cancelRequest };
  }
};

4.4 并发请求处理

当需要同时发起多个请求时,使用并发请求可以显著提升性能

使用 Promise.all

const fetchMultipleData = async () => {
  try {
    const [users, posts, comments] = await Promise.all([
      axios.get('/users'),
      axios.get('/posts'),
      axios.get('/comments')
    ]);
    
    console.log('用户数据:', users.data);
    console.log('文章数据:', posts.data);
    console.log('评论数据:', comments.data);
    
    return { users: users.data, posts: posts.data, comments: comments.data };
  } catch (error) {
    console.error('并发请求失败:', error);
    throw error;
  }
};

使用 axios.all 和 axios.spread

const fetchMultipleData = () => {
  return axios.all([
    axios.get('/users'),
    axios.get('/posts')
  ])
  .then(axios.spread((usersResponse, postsResponse) => {
    return {
      users: usersResponse.data,
      posts: postsResponse.data
    };
  }))
  .catch(error => {
    console.error('并发请求失败:', error);
    throw error;
  });
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值