VUE中对axios的封装

2 篇文章 0 订阅

前言

在VUE项目中进行数据交互使用的比较多的就是axios,新手一般都是安装完axios插件后在需要的地方直接使用axios.get()或axios.post(),我也不例外。在小项目中的确这种方式简单快捷,但是当在大项目中还是这样使用起来就显得非常的繁琐,自己也开始研究如何进行优化,把公共的部分提取出来,减少代码的沉余。但是始终还是觉得自己的想法不够先进,后面在看一个VUE开源项目的时候发现它对axios进行封装的很好,于是借鉴了一下。

目录结构

在src目录下新建文件夹api,api文件夹下新建apis文件夹(存放所有api接口)、urls文件夹(存放所有api接口的url)、axios文件(对axios进行配置)、index.js文件。

axios.js(配置【完整全部内容见最后】)

1.对请求头部进行配置(基础的url、请求超时、headers)

const tokenKey = 'JEECMS-Auth-Token'
const request = axios.create({
  baseURL: process.env.VUE_APP_API_PREFIX,
  timeout: 50000,
  headers: {
    'Content-Type': 'application/json',
    'Redirect-Header': false
  }
})

2.对请求参数进行配置

const baseHeader = () => {  //动态获取token和标志性的ID
  const token = window.localStorage.getItem(tokenKey)
  const siteId = window.localStorage.getItem('siteId')
  return {   //返回新的内容
    [tokenKey]: token,
    siteId
  }
}
request.interceptors.request.use(config => {
  config.headers = Object.assign({}, baseHeader(), config.headers)   //修改headers
  if (!config.url) {   //使用elementUI的消息框进行提示
    Message.error({
      showClose: true,
      message: '接口地址错误',
      type: 'error',
      duration: 3 * 1000
    })
  } else if (config.url.endsWith('/admin/login')) {   //特殊情况处理
    config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
    config.data = qs.stringify(config.data)
  }
  return config
}, error => {   //对请求出错后的处理
  console.log(error)
  return Promise.reject(error)
})

3.对返回参数进行配置

request.interceptors.response.use(response => {
  if (response.data.token && response.data.token !== '') {
    localStorage.setItem(tokenKey, response.data.token)
  }
  return response
}, error => {
  // console.log(error)
  let message = error.message
  if (error.response.status === 404) {
    message = '接口访问失败'
  }
  Message({
    showClose: true,
    message,
    type: 'error',
    duration: 3 * 1000
  })
  return Promise.reject(error)
})

4.对请求结果状态处理

const checkStatus = response => {
  if (response && response.status === 401) {
    window.localStorage.setItem(tokenKey, '')
    const url = window.location.hash.substr(1)
    if (/^\/login/.test(url)) {
      router.push(url)
    } else {
      router.push(`/login?redirect=${escape(url)}`)
    }
    return
  }
  if (response && (response.status === 200 || response.status === 304 || response.status === 400 || response.status === 404)) {
    return response.data
  }
  return {
    status: -404,
    msg: '网络异常'
  }
}

function checkCode (res) {
  if ([501, 502, 503, 506].includes(res.code)) {
    window.localStorage.setItem(tokenKey, '')
    const url = window.location.hash.substr(1)
    if (/^\/login/.test(url)) {
      router.push(url)
    } else {
      router.push(`/login?redirect=${escape(url)}`)
    }
  }
  if (res.code !== 200) {
    Message({
      showClose: true,
      message: res.message || '服务器端错误',
      type: 'error',
      duration: 3 * 1000
    })
  }
  return res
}

 5.导出各种请求方式

export default {
  request (config) {
    return axios.request(config).then(checkStatus).then(checkCode)
  },
  login (url, data) {
    return requestLogin({
      method: 'post',
      url,
      data
    }).then(checkStatus).then(checkCode)
  },
  upload (url, data, onUploadProgress = () => {}) {
    return request({
      method: 'post',
      url,
      headers: { 'Content-Type': 'multipart/form-data' },
      data,
      onUploadProgress
    }).then(checkStatus).then(checkCode)
  },
  download (url, data, onDownloadProgress = () => {}) {
    return request({
      method: 'post',
      url,
      data,
      responseType: 'blob',
      onDownloadProgress
    }).then(checkStatus)
  },
  post (url, data, onUploadProgress = () => {}) {
    return request({
      method: 'post',
      url,
      data,
      onUploadProgress
    }).then(checkStatus).then(checkCode)
  },
  get (url, params, headers = {}) {
    return request({
      method: 'get',
      url,
      params,
      headers
    }).then(checkStatus).then(checkCode)
  },
  put (url, data) {
    return request({
      method: 'put',
      url,
      data
    }).then(checkStatus).then(checkCode)
  },
  patch (url, data) {
    return request({
      method: 'patch',
      url,
      data
    }).then(checkStatus).then(checkCode)
  },
  delete (url, data) {
    return request({
      method: 'delete',
      url,
      data
    }).then(checkStatus).then(checkCode)
  }
}

URL封装(以登陆模块为例)

const prefix = '/admin'

export default {
  // 验证码
  code: '/common/kaptcha',
  // 登陆
  login: `${prefix}/login`,
  // 上传
  upload: `${prefix}/upload/o_upload`,
  // 返回中文首字母
  pinyin: '/language/pinyin',
  // 自动摘要
  summary: '/language/summary',
  // 修改密码
  adminpsw: `${prefix}/users/adminpsw`,
  // 导入word
  docImport: `${prefix}/contentext/docImport`
}

接口封装(以登陆模块为例)

import axios from '../axios'
import loginUrls from '../urls/login'

export default {
  fetchCode () {
    return axios.get(loginUrls.code)
  },
  fetchLogin (data) {
    return axios.login(loginUrls.login, data)
  },
  fetchUpload (data, onUploadProgress) {
    return axios.upload(loginUrls.upload, data, onUploadProgress)
  },
  fetchPinyin (data) {
    return axios.get(loginUrls.pinyin, data)
  },
  fetchSummary (data) {
    return axios.post(loginUrls.summary, data)
  },
  fetchAdminPsw (data) {
    return axios.post(loginUrls.adminpsw, data)
  },
  fetchDocImport (data) {
    return axios.upload(loginUrls.docImport, data)
  }
}

index.js

const modulesFiles = require.context('./apis', true, /\.js$/)
// 这里是webpack的方法,参数说明:要搜索的文件夹目录、是否还应该搜索它的子目录、以及一个匹配文件的正则表达式
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  const value = modulesFiles(modulePath)
  modules = Object.assign(modules, value.default)
  return modules
}, {})

export default modules

如何使用

在需要的地方使用如下方法调用接口

this.fetchLogin(data).then(res => {.....})

给自己做个宣传

本人个人博客:www.dzyong.com

 

附录:axios.js全部内容

import axios from 'axios'
import qs from 'qs'
import { Message } from 'element-ui'
import router from '@/routes'

const tokenKey = 'JEECMS-Auth-Token'
const request = axios.create({
  baseURL: process.env.VUE_APP_API_PREFIX,
  timeout: 50000,
  headers: {
    'Content-Type': 'application/json',
    'Redirect-Header': false
  }
})

const baseHeader = () => {
  const token = window.localStorage.getItem(tokenKey)
  const siteId = window.localStorage.getItem('siteId')
  return {
    [tokenKey]: token,
    siteId
  }
}

request.interceptors.request.use(config => {
  config.headers = Object.assign({}, baseHeader(), config.headers)
  if (!config.url) {
    Message.error({
      showClose: true,
      message: '接口地址错误',
      type: 'error',
      duration: 3 * 1000
    })
  } else if (config.url.endsWith('/admin/login')) {
    config.headers['Content-Type'] = 'application/x-www-form-urlencoded'
    config.data = qs.stringify(config.data)
  }
  return config
}, error => {
  console.log(error)
  return Promise.reject(error)
})

request.interceptors.response.use(response => {
  if (response.data.token && response.data.token !== '') {
    localStorage.setItem(tokenKey, response.data.token)
  }
  return response
}, error => {
  // console.log(error)
  let message = error.message
  if (error.response.status === 404) {
    message = '接口访问失败'
  }
  Message({
    showClose: true,
    message,
    type: 'error',
    duration: 3 * 1000
  })
  return Promise.reject(error)
})

const checkStatus = response => {
  if (response && response.status === 401) {
    window.localStorage.setItem(tokenKey, '')
    const url = window.location.hash.substr(1)
    if (/^\/login/.test(url)) {
      router.push(url)
    } else {
      router.push(`/login?redirect=${escape(url)}`)
    }
    return
  }
  if (response && (response.status === 200 || response.status === 304 || response.status === 400 || response.status === 404)) {
    return response.data
  }
  return {
    status: -404,
    msg: '网络异常'
  }
}

function checkCode (res) {
  if ([501, 502, 503, 506].includes(res.code)) {
    window.localStorage.setItem(tokenKey, '')
    const url = window.location.hash.substr(1)
    if (/^\/login/.test(url)) {
      router.push(url)
    } else {
      router.push(`/login?redirect=${escape(url)}`)
    }
  }
  if (res.code !== 200) {
    Message({
      showClose: true,
      message: res.message || '服务器端错误',
      type: 'error',
      duration: 3 * 1000
    })
  }
  return res
}

// 登录用的请求实例
const requestLogin = axios.create({
  baseURL: process.env.VUE_APP_API_PREFIX,
  timeout: 50000,
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
})

requestLogin.interceptors.request.use(config => {
  config.data = qs.stringify(config.data)
  return config
}, error => {
  return Promise.reject(error)
})

requestLogin.interceptors.response.use(response => {
  return response
}, error => {
  let message = error.message
  if (error.response.status === 404) {
    message = '接口访问失败'
  }
  Message({
    showClose: true,
    message,
    type: 'error',
    duration: 3 * 1000
  })
  return Promise.reject(error)
})

export default {
  request (config) {
    return axios.request(config).then(checkStatus).then(checkCode)
  },
  login (url, data) {
    return requestLogin({
      method: 'post',
      url,
      data
    }).then(checkStatus).then(checkCode)
  },
  upload (url, data, onUploadProgress = () => {}) {
    return request({
      method: 'post',
      url,
      headers: { 'Content-Type': 'multipart/form-data' },
      data,
      onUploadProgress
    }).then(checkStatus).then(checkCode)
  },
  download (url, data, onDownloadProgress = () => {}) {
    return request({
      method: 'post',
      url,
      data,
      responseType: 'blob',
      onDownloadProgress
    }).then(checkStatus)
  },
  post (url, data, onUploadProgress = () => {}) {
    return request({
      method: 'post',
      url,
      data,
      onUploadProgress
    }).then(checkStatus).then(checkCode)
  },
  get (url, params, headers = {}) {
    return request({
      method: 'get',
      url,
      params,
      headers
    }).then(checkStatus).then(checkCode)
  },
  put (url, data) {
    return request({
      method: 'put',
      url,
      data
    }).then(checkStatus).then(checkCode)
  },
  patch (url, data) {
    return request({
      method: 'patch',
      url,
      data
    }).then(checkStatus).then(checkCode)
  },
  delete (url, data) {
    return request({
      method: 'delete',
      url,
      data
    }).then(checkStatus).then(checkCode)
  }
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

前端筱园

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值