# 一、axios 配置管理

# 1、全局配置

  axios 的全局默认配置:

后续我们也可以在 axios 实例上进行自定义配置

axios.defaults.baseURL = 'https://api.example.com'
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'

  每次使用 axios 请求时,都要反复的加上请求基地址,为了简化,我们可以将它提前出来,进行统一配置。

  • main.js
import axios from 'axios'

Vue.prototype.$http = axios
// 配置默认基地址✨
axios.defaults.baseURL = 'http://www.example.top:3006'

# 2、Axios 实例

  在正式的开发环境中,我们往往会将上面的自定义配置弄成一个 axios 实例,方便对自定义配置进行管理。

  • main.js
import request from '@/utils/request.js'
  • request.js

这个文件,后面会进行升级(作为独立模块,进行 axios 封装)

import axios from 'axios'

const request = axios.create({
  baseURL: 'http://www.example.top:3006',
  timeout: 1000
  // ……
})

export default request

  下面,我们来使用一下我们创建的 axios 实例:

这个文件,后面会进行升级(一分为二,进行接口管理)

<template>
  <div class="demo-container">
    <span>{{ username }}</span>
    <button @click="btnFn">获取author</button>
  </div>
</template>

<script>
export default {
  name: 'Demo'
  data() {
    return {
      username: '未知'
    }
  },
  methods: {
    btnFn: function () {
      request.get('/api/getbooks?id=1').then((res) => {
        this.username = res.data.author
      })
    }
  }
}
</script>

# 3、axios 封装 ✨

  但是,如果我们把创建的 axios 实例也搞到到 main.js 中全局使用,那实际上和前面的将它挂载到 vue 原型上是没啥区别。

  那如果进行巧妙的升级呢?

答案

  我们使用 axios 那一定是涉及到 api 请求,那我们为什么不把 axios 实例、api 请求统一放到指定的地方,进行统一管理呢?

提示

  对原生 axios 进行封装处理,其优点如下:

  • 与 vue 项目代码内容解耦,方便维护
  • 当 axios 不在维护时,可直接在 require.js 中使用替代方案

# ① axios 实例封装

  • 新建:utils / request.js

提示

  在真实项目开发中,除了可以使用函数对 axios 进行封装,也有人所有 class 类对 axios 进行封装(个人推荐)。

class 类封装方式
import axios from 'axios'
import { BASE_URL, TIMEOUT } from './config'

class RenRequest {
  constructor(baseURL, timeout) {
    this.instance = axios.create({
      baseURL,
      timeout
    })

    // 响应拦截
    this.instance.interceptors.response.use(
      (res) => {
        return res.data
      },
      (err) => {
        return err
      }
    )
  }

  request(config) {
    return this.instance.request(config)
  }

  get(config) {
    return this.request({ ...config, method: 'get' })
  }

  post(config) {
    return this.request({ ...config, method: 'post' })
  }
}

export default new RenRequest(BASE_URL, TIMEOUT)
import axios from 'axios'

export const baseURL = 'http://www.example.top:3006'

const request = axios.create({
  baseURL: baseURL,
  timeout: 1000
  // ……
})

// ……
// axios拦截器内容
// ……

export default ({ method = 'GET', url, data = {}, params = {}, headers = {} }) => {
  return request({
    method,
    url,
    data,
    params,
    headers
  })
}

  若要将 axios 改为 jQuery 的 ajax 请求:

jQuery 化
import $ from 'jquery'

export default ({
  method = 'GET',
  url,
  data = {},
  params = {},
  headers = {}
}) => {
  return newPromise(resolve,reject) => {
    $.ajax({
      type: method,
      url,
      data,
      headers,
      success: (req) => {
        resolve(res)
      },
      error: (err) => {
        reject(err)
      }
    })
  }
}

# ② api 接口管理

  • api / index.js
import request from '@/utils/request.js'

// 接口请求测试
export const getDemoAPI = () => {
  return request({
    method: 'GET',
    url: '/api/getbooks',
    params: { id: 1 }
  })
}
  • 任意组件(使用)
import { getDemoAPI } from '@/api/index.js'

export default {
  methods: {
    async getDemoFn() {
      const { data: res } = await getDemoAPI()
      console.log(res)
    }
  }
}

  若还想对 api / index.js 进行模块化:

api 接口模块化
  • 新建:api / index.js
import { recommendMusic } from './home'
import { getCommentList } from './comment'

export const recommendMusicAPI = recommendMusic // 首页 - 推荐歌单接口

export const getCommentListAPI = getCommentList // 评论页 - 歌曲评论接口
  • 编写接口
// api / comment.js文件
import request from '@/utils/request'

/**
 * 评论页 - 歌曲评论接口
 * @param {*} params
 * @returns Promise对象
 */
export const getCommentList = (params) =>
  return request({
    url: '/comment/music',
    params
  })
  • 使用接口
import { getCommentListAPI } from '@/api'

export default {
  methods: {
    async getCommentListFn() {
      const { data: res } = await getCommentListAPI({
        id: this.$route.query.id,
        limit: 15,
        offset: (this.page - 1) * 15
      })
      // ……
    }
  }
}

# 二、Axios 拦截器

https://www.axios-http.cn/docs/interceptors

# 1、效果图解

作用:

  • 在请求或响应被 then 或 catch 处理前拦截它们。

图解:


# 2、基础结构

  axios 拦截器的使用还是非常简单的。

  我们可以在回调函数中通过参数获取请求/响应的 config / response 对象

使用示例
const request = axios.create({
  //
})

// 添加请求拦截器
request.interceptors.request.use(
  (config) => {
    console.log('请求拦截成功')

    return config
  },
  (error) => {
    console.log('请求拦截失败')

    return error
    // return Promise.reject(error)
  }
)

// 添加响应拦截器
request.interceptors.response.use(
  (response) => {
    console.log('响应拦截成功')

    return response
  },
  (error) => {
    console.log('响应拦截失败')

    return error
    // return Promise.reject(error)
  }
)
const interceptorsReq =  axios.interceptors.request.use(成功回调,失败回调)
axios.interceptors.request.eject(interceptorsReq)


const interceptorsRes = axios.interceptors.response.use(成功回调,失败回调)
axios.interceptors.request.eject(interceptorsRes)

# 3、应用场景

开发应用
  • utils/request.js
axios.interceptors.request.use(
  function (config) {
    // 发送token✨(用于服务端校验)
    const token = localStorage.getItem('token')
    config.headers.Authorization = `Bearer ${token}`

    return config
  },
  function (error) {
    return Promise.reject(error)
  }
)

axios.interceptors.response.use(
  function (response) {
    // 客户端存储🚩token
    // console.log(response.headers)

    const { authorization } = response.headers
    authorization && localStorage.setItem('token', authorization)

    return response
  },
  function (error) {
    // token过期✨处理
    if (error.response.status === 401) {
      localStorage.removeItem('token')
      location.href = '/login'
    }
    return Promise.reject(error)
  }
)
  • 请求拦截
request.interceptors.request.use(
  (config) => {
    // 应用1:开始loading动画

    // 应用2:对原config配置进行修改
    // - 2.1 添加/修改headers(可能与token/ookie相关)
    // - 2.2 对请求参数进行处理

    return config
  },
  (error) => {
    return error
  }
)
  • 响应拦截
request.interceptors.response.use(
  (response) => {
    // 应用1:结束loading动画

    // 应用2:对response内容进行拦截
    // - 2.1 获取headers(可能与token/ookie相关)
    // - 2.2 对获取的data数据进行处理

    return response
  },
  (error) => {
    return error
  }
)

# 三、Axios 的三种请求方式

https://cloud.tencent.com/developer/article/1709763

# 1、json 数据

Content-Type: application/json

let data = { username: 'lencamo', password: '666666' }

const { data: res } = await loginAPI(data)

# 2、表单数据

Content-Type: multipart/form-data

// 一、创建 FormData 表单数据对象
// FormData类是THML5的内容(是一个用于装文件的容器)
const data = new FormData()

// 二、向 FormData 中追加数据
// 方式1
// fd.append('title', this.pubForm.title)
// fd.append('cate_id', this.pubForm.cate_id)
// fd.append('content', this.pubForm.content)
// fd.append('cover_img', this.pubForm.cover_img)
// fd.append('state', this.pubForm.state)

// 方式2:使用Object.keys加forEach()
Object.keys(this.pubForm).forEach((key) => {
  data.append(key, this.pubForm[key])
})
console.log(data)

// 三、发起请求
const { data: res } = await uploadArticleAPI(data)

# 3、参数格式

Content-Type: application/x-www-form-urlencoded

// 默认情况下在安装完axios后就可以使用qs库
import qs from 'Qs'

let data = { code: '3', tip: '2545536' }

const { data: res } = await getNewsMsgAPI(qs.stringify({ data }))
更新于 : 8/7/2024, 2:16:31 PM