Vue基础教程(186)axios配置默认选项:别再用重复代码折磨自己了!Axios默认配置让你的开发效率翻倍

Axios默认配置提升开发效率

还记得刚学Vue时被HTTP请求支配的恐惧吗?每个组件里都在重复写着一模一样的代码:

// 每个组件都在重复这些代码,烦不烦?
axios.post('https://api.yoursite.com/v1/users', data, {
  headers: {
    'Authorization': 'Bearer ' + token,
    'Content-Type': 'application/json'
  }
})

一个月后,后端告诉你:“哥们,域名从 https://api.yoursite.com 换成 https://api.newdomain.com 了...”

然后你哭着在整个项目里查找替换几十个接口地址——别问我是怎么知道的,说多了都是泪。

为什么你需要Axios默认配置?

Axios默认配置就像是给你的请求找了个贴心管家,把那些重复性的琐事统统搞定。想象一下,你不再需要:

  • 在每个请求里写完整的URL
  • 手动添加认证token
  • 重复设置content-type
  • 为每个请求单独处理错误

Axios的默认配置能帮你做什么?

简单说就是“一次设置,到处使用”。你定义一次规则,Axios会在每个请求中自动应用这些规则。这不仅仅是代码整洁的问题,更是维护性和开发效率的质的飞跃。

手把手配置:从入门到精通

1. 基础配置:让你的代码瞬间清爽

先来看一个最基本的配置:

// axios默认配置
axios.defaults.baseURL = 'https://api.yoursite.com/v1'
axios.defaults.timeout = 10000 // 10秒超时
axios.defaults.headers.common['Content-Type'] = 'application/json'

// 然后你的请求就变成了这样:
// 之前:axios.post('https://api.yoursite.com/v1/users', data, config)
// 现在:
axios.post('/users', data) // 清爽!

看到区别了吗?baseURL 设置了基础路径,后续所有相对路径都会自动拼接。这就好比给所有请求加了个通用前缀,再也不用担心域名变更了。

2. 实战中的完整配置示例

光说不练假把式,来看一个真实项目中的配置:

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

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // 从环境变量读取
  timeout: 15000, // 15秒超时
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

// 请求拦截器 - 在发送请求前做点什么
service.interceptors.request.use(
  config => {
    // 每次请求自动添加token
    const token = localStorage.getItem('access_token')
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`
    }
    return config
  },
  error => {
    return Promise.reject(error)
  }
)

// 响应拦截器 - 在收到响应后做点什么
service.interceptors.response.use(
  response => {
    // 如果后台有统一的数据结构,可以在这里统一处理
    const res = response.data
    if (res.code === 200) {
      return res
    } else {
      // 处理业务错误
      alert(res.message || '请求失败')
      return Promise.reject(new Error(res.message || 'Error'))
    }
  },
  error => {
    // 处理HTTP错误
    if (error.response?.status === 401) {
      // token过期,跳转到登录页
      localStorage.removeItem('access_token')
      window.location.href = '/login'
    } else if (error.response?.status === 500) {
      alert('服务器内部错误,请稍后重试')
    }
    return Promise.reject(error)
  }
)

export default service

然后在你的Vue组件中:

// 在组件中使用
import request from '@/utils/request'

export default {
  methods: {
    async getUserInfo() {
      try {
        // 看,多简洁!
        const userData = await request.get('/user/info')
        const listData = await request.post('/list', { page: 1 })
        
        this.user = userData
        this.list = listData
      } catch (error) {
        console.log('请求失败', error)
      }
    }
  }
}
3. 环境区分:开发、测试、生产无缝切换

真实项目中,不同环境需要不同的配置:

// .env.development
VUE_APP_BASE_API = 'https://dev-api.yoursite.com'

// .env.production  
VUE_APP_BASE_API = 'https://api.yoursite.com'

// 在axios配置中使用
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API,
  // ...其他配置
})

这样,打包到不同环境时会自动使用对应的接口地址,再也不用手动修改了。

拦截器:Axios的灵魂所在

如果说默认配置是基础装备,那拦截器就是神级装备。它让你能够在请求和响应的生命周期中插入自定义逻辑。

请求拦截器的妙用:

service.interceptors.request.use(
  config => {
    // 显示loading
    showLoading()
    
    // 记录请求开始时间(用于性能监控)
    config.metadata = { startTime: new Date() }
    
    // 如果是文件上传,修改content-type
    if (config.data instanceof FormData) {
      config.headers['Content-Type'] = 'multipart/form-data'
    }
    
    return config
  }
)

响应拦截器的威力:

service.interceptors.response.use(
  response => {
    // 隐藏loading
    hideLoading()
    
    // 计算请求耗时
    const endTime = new Date()
    const duration = endTime - response.config.metadata.startTime
    console.log(`请求 ${response.config.url} 耗时 ${duration}ms`)
    
    return response.data
  },
  error => {
    hideLoading()
    
    // 统一错误处理
    if (!error.response) {
      // 网络错误
      alert('网络连接失败,请检查网络设置')
    }
    
    return Promise.reject(error)
  }
)

高级技巧:让你的Axios配置更智能

1. 重试机制:网络不稳定时的救星
service.interceptors.response.use(
  response => response,
  async error => {
    const { config, response } = error
    
    // 只在网络错误或5xx错误时重试
    if (!response || response.status >= 500) {
      if (!config.retryCount) {
        config.retryCount = 0
      }
      
      if (config.retryCount < 3) {
        config.retryCount++
        // 等待2的n次方秒后重试(2, 4, 8秒)
        const waitTime = Math.pow(2, config.retryCount) * 1000
        await new Promise(resolve => setTimeout(resolve, waitTime))
        return service(config)
      }
    }
    
    return Promise.reject(error)
  }
)
2. 请求取消:避免重复请求
const pendingRequests = new Map()

// 生成请求的唯一标识
function getRequestKey(config) {
  return [config.method, config.url].join('&')
}

// 请求拦截器中
service.interceptors.request.use(config => {
  const key = getRequestKey(config)
  if (pendingRequests.has(key)) {
    // 取消重复请求
    pendingRequests.get(key)('取消重复请求')
  }
  
  config.cancelToken = new axios.CancelToken(cancel => {
    pendingRequests.set(key, cancel)
  })
  
  return config
})

// 响应拦截器中
service.interceptors.response.use(
  response => {
    const key = getRequestKey(response.config)
    pendingRequests.delete(key)
    return response
  },
  error => {
    if (axios.isCancel(error)) {
      console.log('请求被取消:', error.message)
    }
    return Promise.reject(error)
  }
)
3. 文件上传进度监控
// 上传文件时显示进度
async uploadFile(file, onProgress) {
  const formData = new FormData()
  formData.append('file', file)
  
  const response = await request.post('/upload', formData, {
    onUploadProgress: progressEvent => {
      if (onProgress) {
        const percent = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        )
        onProgress(percent)
      }
    }
  })
  
  return response
}

常见坑点及解决方案

坑点1:默认配置不生效

// 错误写法:创建实例后修改defaults对实例无效
const instance = axios.create()
instance.defaults.timeout = 1000 // 这样写无效!

// 正确写法:在create时传入配置,或使用instance的配置
const instance = axios.create({
  timeout: 1000 // 正确
})

// 或者
instance.defaults.timeout = 1000 // 这样也正确

坑点2:拦截器中的异步问题

// 错误:在拦截器中直接使用async/await但不返回
service.interceptors.request.use(async config => {
  await someAsyncOperation() // 这样会出问题!
  return config
})

// 正确:确保正确处理异步
service.interceptors.request.use(async config => {
  await someAsyncOperation()
  return config // 正确返回
})

完整示例:开箱即用的Axios配置

最后,送大家一个生产环境可用的完整配置:

// src/utils/request.js
import axios from 'axios'
import { Message } from 'element-ui' // 如果你用了Element UI

class Request {
  constructor() {
    this.instance = axios.create({
      baseURL: process.env.VUE_APP_BASE_API,
      timeout: 15000,
      withCredentials: true // 跨域时携带cookie
    })
    
    this.setupInterceptors()
  }
  
  setupInterceptors() {
    // 请求拦截
    this.instance.interceptors.request.use(
      config => {
        // 添加时间戳防止缓存
        if (config.method === 'get') {
          config.params = {
            ...config.params,
            _t: Date.now()
          }
        }
        
        const token = localStorage.getItem('token')
        if (token) {
          config.headers['Authorization'] = `Bearer ${token}`
        }
        
        return config
      },
      error => Promise.reject(error)
    )
    
    // 响应拦截
    this.instance.interceptors.response.use(
      response => {
        const { data } = response
        
        // 根据你的后端数据结构调整
        if (data.code === 0 || data.success) {
          return data
        } else {
          Message.error(data.message || '请求失败')
          return Promise.reject(new Error(data.message || 'Error'))
        }
      },
      error => {
        const { status } = error.response || {}
        
        switch (status) {
          case 400:
            Message.error('请求错误')
            break
          case 401:
            Message.error('未授权,请重新登录')
            localStorage.removeItem('token')
            setTimeout(() => {
              window.location.href = '/login'
            }, 1500)
            break
          case 403:
            Message.error('拒绝访问')
            break
          case 404:
            Message.error('请求地址出错')
            break
          case 500:
            Message.error('服务器内部错误')
            break
          default:
            Message.error('网络连接失败')
        }
        
        return Promise.reject(error)
      }
    )
  }
  
  get(url, params = {}) {
    return this.instance.get(url, { params })
  }
  
  post(url, data = {}) {
    return this.instance.post(url, data)
  }
  
  put(url, data = {}) {
    return this.instance.put(url, data)
  }
  
  delete(url, params = {}) {
    return this.instance.delete(url, { params })
  }
}

export default new Request()

结语

Axios的默认配置和拦截器就像是给你的项目请了一个24小时在线的贴心助理。它帮你处理各种重复劳动,让你能专注于核心业务逻辑。

从今天开始,告别重复代码,拥抱高效的Axios配置吧!你的键盘会感谢你,你的队友也会感谢你——毕竟,谁不喜欢简洁清晰的代码呢?

记住:好的配置不是炫技,而是为了让代码更可维护、更健壮、更优雅。现在就去优化你的Axios配置吧,保证让你直呼“真香”!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值