# 一、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 }))
← Axios请求(上) 【接口风格】 →