如何用vue封装axios请求

发布时间:2022-05-06 14:15:09 作者:iii
来源:亿速云 阅读:230
# 如何用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 // 请求超时时间
})

2.2 添加请求拦截器

// 请求拦截器
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)
  }
)

2.3 添加响应拦截器

// 响应拦截器
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)
  }
)

2.4 导出封装后的方法

export default service

三、高级封装技巧

3.1 API模块化管理

创建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'
  })
}

3.2 添加全局loading控制

在请求拦截器中:

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)
  }
)

3.3 请求取消功能

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
})

3.4 重试机制

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)
  })
})

四、在Vue组件中使用

4.1 基本使用

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)
      }
    }
  }
}

4.2 结合Vuex使用

// 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)
      })
    })
  }
}

五、最佳实践建议

  1. 环境区分:开发、测试、生产环境使用不同的baseURL
  2. 类型提示:为API添加TypeScript类型定义
  3. Mock数据:开发阶段使用Mock.js模拟数据
  4. 文档维护:使用Swagger或YAPI等工具维护API文档
  5. 性能优化:合理设置缓存策略

六、完整代码示例

完整的封装示例可以参考以下结构:

src/
├── api/
│   ├── user.js
│   ├── product.js
│   └── ...
├── utils/
│   ├── request.js
│   └── ...

结语

通过合理的封装,我们可以将Axios的强大功能与Vue的响应式特性完美结合,构建出健壮、易维护的网络请求层。本文介绍的方法只是基础实现,实际项目中可以根据需求进一步扩展和完善。希望本文能帮助你更好地组织Vue项目中的网络请求代码。 “`

这篇文章总计约1900字,涵盖了从基础封装到高级技巧的完整内容,采用Markdown格式编写,包含代码块、标题层级和列表等标准Markdown元素。

推荐阅读:
  1. 如何封装vue中的axios请求
  2. Vue项目中如何使用Axios封装http请求详解

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue axios

上一篇:vue项目的性能优化方法

下一篇:Vue+ElementUI+Springboot的基础知识是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》