介绍
https://github.com/axios/axios
中文说明
安装
1、脚手架里面安装
2、通过npm安装
npm i axios -S
3、通过cdn引入
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- 或 -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
引入
在main.js中,添加如下代码
//1.引入axios
import axios from 'axios'
//2.设置默认请求的url
axios.defaults.baseURL = 'http://mockjs.com/api'
//3.设置Vue的默认http请求用axios
Vue.prototype.$http = axios
使用
请求方式
后面模块主要是使用axios(config)的方式
常见属性
单个请求
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios';
//阻止启动生产消息,如see more tips at xxx.com这些提示
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
//发送一个请求,默认是get,本地也算跨域
axios({
url:'http://localhost:81/ax.php'
}).then(res => { //then支持一个回调函数
console.log(res);
})
并发请求 axios.all([])
axios.all([
axios({}),
axios({})
]
).then(res => {
//返回一个数组,里面分别是多个请求的结果
console.log(res[0])
console.log(res[1])
}
)
axios.all([
axios({}),
axios({})
]
).then(axios.spread(
//axios.spread(回调函数),可以直接展开
(res0,res1) => {
console.log(res0)
console.log(res1)
}
)
模拟请求
网站:http://httpbin.org/,可以模拟后端,你可以发送各种各样的请求获取数据
====================
封装
好处
为了避免对某个框架(如这里的axios)过度依赖,我们需要对这个框架封装到1个文件中,项目只要都引用这个文件即可。
这样假如axios不再维护要换框架,此时只要改那个文件即可。
JS封装
建议创建network文件夹,里面创建一个专门发送请求的文件
//1.引入框架(这里是axios)
import axios from 'axios'
// 实际上就是创建了axios的对象实例,也就是一个对象,对象里面有一些方法和属性
//2.导出一个请求函数request到全局,给其他需要的组件引用
/**
* @param {Object} config 全局配置
* @param {Object} success 请求成功时返回
* @param {Object} failure 请求失败时返回
*/
export function request(config, success, failure) {
//3.创建这个请求的实例x = axios.create({请求的配置})
const x = axios.create({
//设置路径,可以在其他组件内具体使用时,使用具体的url,而不是在这里统一设置
url:"/",
//设置基本的路径,自动加在 `url` 前面,除非 `url` 是一个绝对 URL
baseURL: "http://localhost:80/php/php",
//设置请求的方法,默认是get
method:"get" ,
// `params` 即将与请求一起发送的get请求的 URL 参数,如/php?ID=12345
// 必须是一个无格式对象(plain object)或 URLSearchParams 对象
// params: {
// ID: 12345
// },
//设置请求方法post
// method:"post" ,
// `data` 是作为post的请求主体被发送的数据
// 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
// 在没有设置 `transformRequest` 时,必须是以下类型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 浏览器专属:FormData, File, Blob
// - Node 专属: Stream
// data: {
// firstName: 'Fred'
// },
// `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
// 如果请求话费了超过 `timeout` 的时间,请求将被中断
timeOut: 5000,
// `headers` 是即将被发送的自定义请求头
// headers: {'X-Requested-With': 'XMLHttpRequest'},
// `transformRequest` 允许在向服务器发送前,修改请求数据
// 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
// transformRequest: [function (data, headers) {
// // 对 data 进行任意转换处理
// return data;
// }],
// `transformResponse` 拿到服务器数据后,在传递给 then/catch 前,允许修改响应数据
// transformResponse: [function (data) {
// // 对 data 进行任意转换处理
// return data;
// }],
})
//4.当外部调用request函数时,用实例x的配置,发送真正的网络请求
//axios是继承promise的,因此可以直接调用success,failure 作为
//promise的resole 和 reject
return x(config, success, failure)
}
需要用到这个请求时,在模板.vue内,引入并使用
<template>
<el-button type="success" @click="getPerson">成功按钮</el-button>
</template>
<script>
//1.引入这个请求的这个函数
import { request } from '../network/request.js';
export default {
data() {
return {};
},
methods: {
getPerson() {
//2.创建函数,调用request请求
request({
url: 'getUser.php',
})
//成功时返回结果res
.then(res => {
console.log(res.data);
})
//失败时返回结果err
.catch(err =>{
console.log(err);
})
}
}
};
</script>
TS封装
思路就是,把 axios 的实例 axios.create(config),封装成一个自定义请求类 YJLRequest,通过x = new YJLRequest( config ) 的方式创建请求实例,最后通过调用这个 x 的方法发送请求。
为什么要封装成一个类?这样配置可以更灵活,比如
请求1是使用配置1、配置2,就把 请求1 = new YJLRequest( { 配置1 , 配置2} ),直接调用请求1.request() 发送。
请求2是使用配置2、配置3,就把 请求2 = new YJLRequest( { 配置2 , 配置3} ),直接调用请求2.request() 发送。
如果你只是把axios封装成一个函数,这样请求1和请求2共用的是同一个实例,如果配置不一样会比较麻烦(比如配置1是超时时间10秒,配置3是超时时间20秒),每次发送都要手动先修改配置。
1、封装基础的请求类
下面是以 Ant Design Vue 2.x 为例子,
把弹窗提示message 和 提示框notification 封装进来,以及把全局Loading封装进来,这样好处是每一个请求开始时都会全屏显示加载中,请求结束后自动取消加载中,若返回的是成功的结果,自动显示操作成功;若返回失败的结果,自动弹出提示框显示失败的内容。
这样不用在外面页面单独配置这些。
而且自定义了3重拦截器,
1、在请求1里面可以自定义拦截器
2、给所有的axios配置了通用的拦截器(弹窗提示message、提示框notification、 全局Loading)
3、外部页面使用时可以自定义拦截器
// =================== 0、引入 ===================
import axios from "axios"
// AxiosInstance 为axios的实例类型
import type { AxiosInstance} from "axios"
// 引入 其他ui组件的加载中弹窗和弹窗的类型
import { message, notification } from "ant-design-vue"
import store from "@/store"
// =================== 1、定义 自定义请求类的 接口 ===================
import type { myRequestConfig,myRequestInterceptors } from "./type";
// =================== 2、封装请求类 ===================
/**
* 自定义请求类;
* 用类进行封装,封装性会更强,而且可以有多个不同的实例
*/
class YJLRequest {
// =================== 2.1、类的基本属性 ===================
/** 储存axios的实例 */
instance: AxiosInstance
/** 自定义拦截器 */
interceptors?: myRequestInterceptors
// =================== 2.2、构造函数 ===================
/** 自定义请求 的构造器 */
constructor(config: myRequestConfig) {
// 创建 axios 实例
this.instance = axios.create(config)
// 自定义拦截器,从外面的config传入
this.interceptors = config.interceptors
// =================== 2.2.1、拦截器 ===================
// 1、从 config 中取出自定义拦截器
// 拦截请求
this.instance.interceptors.request.use(
this.interceptors?.requestInterceptor,
this.interceptors?.requestInterceptorCatch
)
// 拦截响应
this.instance.interceptors.response.use(
this.interceptors?.responseInterceptor,
this.interceptors?.responseInterceptorCatch
)
// 2.添加所有的实例都有的拦截器
// 拦截请求
this.instance.interceptors.request.use(
// 发送请求拦截
(config) => {
console.log("所有的实例都有的拦截器: 请求成功拦截")
// 全局加载中
store.commit("showLoading")
return config
},
(err) => {
console.log("所有的实例都有的拦截器: 请求失败拦截")
// 失败提示
notification["error"]({
message: "发送请求失败",
description: `失败原因为:${err}`
})
return err
}
)
// 拦截响应
this.instance.interceptors.response.use(
// 拦截响应
(res) => {
console.log("所有的实例都有的拦截器: 响应成功拦截")
// 取消全局加载中
store.commit("hiddenLoading")
// 响应成功,获取data
const data = res.data
// 这里可以根据不同的返回情况,设置不同的提示
if (res.status === 200) {
// 成功提示
if (!(config.hiddenSuccessMessage === true)) {
message.success({
content: "操作成功",
duration: 1
})
}
return data
} else {
// 失败提示
notification["error"]({
message: "响应失败",
description: `错误代码为:${res.status}`
})
return data
}
},
(err) => {
console.log("所有的实例都有的拦截器: 响应失败拦截")
// 取消全局加载中
store.commit("hiddenLoading")
// 这里可以判断不同的HttpErrorCode显示不同的错误信息
// 失败提示
notification["error"]({
message: "响应失败",
description: `失败原因:${err}`
})
return err
}
)
}
// =================== 2.3、请求方法 ===================
/** 发送请求方法 */
request<T>(config: myRequestConfig<T>): Promise<T> {
// 如果有请求的拦截器,这里可以在传入的时候给你修改一下配置
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
// 返回 Promise ,让外面可以通过 .then 接收res 或 err
return new Promise((resolve, reject) => {
// 1.单个请求对请求config的处理
if (config.interceptors?.requestInterceptor) {
config = config.interceptors.requestInterceptor(config)
}
// 通过 axios 实例的 request 方法发送请求
this.instance
.request<any,T>(config)
.then((res) => {
// 1.单个请求对数据的处理
if (config.interceptors?.responseInterceptor) {
res = config.interceptors.responseInterceptor(res)
}
// 2.将结果resolve返回出去
resolve(res)
})
.catch((err) => {
reject(err)
})
})
}
// 发送get请求
get<T>(config: myRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'GET' })
}
// 发送post请求
post<T>(config: myRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'POST' })
}
// 发送delete请求
delete<T>(config: myRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'DELETE' })
}
// 发送patch请求
patch<T>(config: myRequestConfig<T>): Promise<T> {
return this.request<T>({ ...config, method: 'PATCH' })
}
}
export default YJLRequest
2、封装请求函数
// 网络请求统一的出口
// import yjlRequest from "@/service/"
import YJLRequest from "@/service/request"
/**
* 自定义请求的实例
*/
const yjlRequest = new YJLRequest({
// 这里的类型是 myRequestConfig 类型
baseURL:"/api",
// hiddenSuccessMessage:true
})
// 可以定义多个请求实例,不同实例有不同的默认配置,很灵活
// export const yjlRequest2 = new YJLRequest()
export default yjlRequest
3、外部使用
<script setup lang="ts">
import yjlRequest from "@/network"
/** 服务器返回的结果类型,自己根据实际情况定义 */
interface DataType {
path: string
httpMethod: string
headers: any
queryStringParameters: any
isBase64Encoded: boolean
body: any
}
const testFun = () => {
yjlRequest
.get<DataType>({
url: "/http/testFun"
})
.then((res) => {
console.log(`res`, res)
})
}
</script>
====================
拦截器
用于发送请求或者得到相应结果时拦截,进行对应的处理
拦截请求
1.用于改变本次请求的配置,用来满足接受服务器的要求
2.可以用于播放请求中的动画,如点击按钮后有个图标在转(拦截拦截,然后播放图标动画),有回应时停止转动(拦截回应,然后停止 播放动画)
3.某些请求,必须携带一些特殊的信息(比如登录的token)
例如打开页面,就会发送请求给服务器,此时拦截,判断是否登录了,如果没登录就跳转到登录页面;如果登录了就继续发送请求
4、请求失败时,可以显示失败的原因
//拦截请求
axios.interceptors.request.use(config => {
//请求发送成功时,执行这里的代码
//config指的是这次拦截的请求的配置config
//拦截后,必须用return 把请求发回出去,否则就只光拦截了
return config
}, error => {
//请求发送失败时,执行这里的代码
});
拦截响应
1、可以对服务器回应的数据作基本的转化
2、响应失败时,可以显示失败的原因
//响应拦截
axios.interceptors.response.use(res => {
//成功接收服务器回应时,执行这里的代码
//config指的是这次拦截的请求返回结果的config
//拦截后,必须用return 把请求发回出去,否则就只光拦截了
//一般只需要返回data就可以了,其他的没什么用
return res.data;
}, error => {
NProgress.done();
return Promise.reject(new Error(error));
})