您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        # 如何用Vue封装Axios请求
## 前言
在现代前端开发中,网络请求是必不可少的部分。Axios作为当前最流行的HTTP客户端之一,以其简洁的API和强大的功能被广泛使用。而在Vue项目中,合理地封装Axios不仅能提高代码复用性,还能统一管理请求逻辑。本文将详细介绍如何在Vue项目中优雅地封装Axios请求。
## 一、为什么需要封装Axios
### 1.1 原始Axios使用的痛点
直接使用Axios虽然简单,但在实际项目中会面临:
- 每个请求都需要重复配置基础URL、headers等
- 缺乏统一的错误处理机制
- 难以集中管理API接口
- 不方便添加全局loading状态
- 难以实现请求取消等功能
### 1.2 封装带来的优势
通过封装可以实现:
- **统一配置**:基础路径、超时时间等
- **拦截器管理**:请求/响应拦截处理
- **API集中管理**:所有接口统一维护
- **更好的扩展性**:便于添加新功能
## 二、基础封装实现
### 2.1 创建axios实例
首先在项目中创建`src/utils/request.js`文件:
```javascript
import axios from 'axios'
// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // 从环境变量获取基础URL
  timeout: 10000 // 请求超时时间
})
// 请求拦截器
service.interceptors.request.use(
  config => {
    // 在发送请求前可以做些什么
    // 例如:添加token
    const token = localStorage.getItem('token')
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  error => {
    // 对请求错误做些什么
    return Promise.reject(error)
  }
)
// 响应拦截器
service.interceptors.response.use(
  response => {
    // 对响应数据做点什么
    const res = response.data
    
    // 假设后端返回的数据格式为 { code: 200, data: {}, message: '' }
    if (res.code !== 200) {
      // 处理业务错误
      return Promise.reject(new Error(res.message || 'Error'))
    } else {
      return res.data
    }
  },
  error => {
    // 对响应错误做点什么
    if (error.response) {
      // 处理HTTP状态码错误
      switch (error.response.status) {
        case 401:
          // 跳转到登录页
          break
        case 403:
          // 提示权限不足
          break
        case 404:
          // 资源不存在
          break
        case 500:
          // 服务器错误
          break
      }
    }
    return Promise.reject(error)
  }
)
export default service
创建src/api目录,按模块划分API:
// src/api/user.js
import request from '@/utils/request'
export function login(data) {
  return request({
    url: '/user/login',
    method: 'post',
    data
  })
}
export function getUserInfo() {
  return request({
    url: '/user/info',
    method: 'get'
  })
}
在请求拦截器中:
let loadingInstance
service.interceptors.request.use(config => {
  loadingInstance = Loading.service({
    lock: true,
    text: '加载中...',
    background: 'rgba(0, 0, 0, 0.7)'
  })
  return config
})
service.interceptors.response.use(
  response => {
    loadingInstance.close()
    return response
  },
  error => {
    loadingInstance.close()
    return Promise.reject(error)
  }
)
const pendingMap = new Map()
const getPendingKey = (config) => {
  return [config.method, config.url].join('&')
}
service.interceptors.request.use(config => {
  const key = getPendingKey(config)
  if (pendingMap.has(key)) {
    const cancel = pendingMap.get(key)
    cancel()
    pendingMap.delete(key)
  }
  config.cancelToken = new axios.CancelToken(cancel => {
    pendingMap.set(key, cancel)
  })
  return config
})
service.interceptors.response.use(response => {
  const key = getPendingKey(response.config)
  pendingMap.delete(key)
  return response
})
const retryDelay = 1000 // 重试延迟
const retryCount = 3 // 最大重试次数
service.interceptors.response.use(undefined, error => {
  const config = error.config
  if (!config || !config.retry) return Promise.reject(error)
  
  config.__retryCount = config.__retryCount || 0
  if (config.__retryCount >= retryCount) {
    return Promise.reject(error)
  }
  
  config.__retryCount += 1
  return new Promise(resolve => {
    setTimeout(() => resolve(service(config)), retryDelay)
  })
})
import { login } from '@/api/user'
export default {
  methods: {
    async handleLogin() {
      try {
        const res = await login({
          username: 'admin',
          password: '123456'
        })
        console.log('登录成功', res)
      } catch (error) {
        console.error('登录失败', error)
      }
    }
  }
}
// store/modules/user.js
import { login, getUserInfo } from '@/api/user'
const actions = {
  login({ commit }, userInfo) {
    return new Promise((resolve, reject) => {
      login(userInfo).then(res => {
        commit('SET_TOKEN', res.token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  }
}
完整的封装示例可以参考以下结构:
src/
├── api/
│   ├── user.js
│   ├── product.js
│   └── ...
├── utils/
│   ├── request.js
│   └── ...
通过合理的封装,我们可以将Axios的强大功能与Vue的响应式特性完美结合,构建出健壮、易维护的网络请求层。本文介绍的方法只是基础实现,实际项目中可以根据需求进一步扩展和完善。希望本文能帮助你更好地组织Vue项目中的网络请求代码。 “`
这篇文章总计约1900字,涵盖了从基础封装到高级技巧的完整内容,采用Markdown格式编写,包含代码块、标题层级和列表等标准Markdown元素。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。