axios学习
由于Vue中整体都没有使用到jQuery,所以使用jQuery封装的ajax肯定不好,为了使用一个小功能导入一个这么重量级的框架肯定亏了。而且,Vue作者推荐在vue中如果想要进行网络请求的话,使用axios框架。axios还支持Promise,所以在vue中使用axios是一个很好的选择。
一、在vue项目中安装axios框架
cnpm install axios --save
二、基本使用
axios()方法默认发送get请求
import axios from 'axios'
axios({
url:'',
//如果get请求需要携带一些参数的话,在这里添加一个params属性
params: {
key: value,
key: value
}
//axios会自动将这些param给通过
//key=value&key=value的方式拼接到url的?后面
}).then(res => {
console.log(res);
})
axios默认会封装一个Promise返回,所以可以使用then直接接收数据,就不用像jQuery一样,success后调用回调了。在axios调用resolve返回的对象中有个data属性,data属性保存着从服务器收到的数据。
修改成post请求
import axios from 'axios'
axios({
url:'',
//如果post请求需要携带一些参数的话,在这里添加一个data属性
method:'post',
data: {
key: value,
key: value
}
//axios会自动将这些data给放入到请求体中
}).then(res => {
console.log(res);
})
三、发送并发请求
前面学习Promise的时候,讲过Promise有个all方法,可以用来发送一些并发的请求,就是几个请求都拿到才进行操作。
在axios中也有个all方法,和Promise.all的使用一模一样,其实axios()就是对Promise又进行了一层封装,它本身返回一个Promise对象,所以axios()和new Promise()差不多。
axios.all([
axios({
url:'',
params: {
key: value,
key: value
}
}),
axios({
url:'',
params: {
key: value,
key: value
}
})
]).then(results => {
console.log(results);
})
axios.all返回一个数组,可以通过axios.spread来将数组展开
.then(axios.spread((res1,res2)=> {
console.log(res1);
console.log(res2);
}))
其实就像是这样,把数组解构出来而已
.then(([res1,res2])=> {
console.log(res1);
console.log(res2);
})
四、全局配置
有些配置,比如说baseURL,在当前项目的所有网络请求中可能都是请求同一个服务器的数据,那么baseURL都是相同的,如果像这样每个请求都设置的话,肯定是麻烦。
axios.all([
axios({
baseURL:'',
url:'',
}),
axios({
baseURL:'',
url:'',
})
]).then(axios.spread((res1,res2)=> {
console.log(res1);
console.log(res2);
}))
这时候就可以设置一个全局的配置
axios.defaults.baseURL = ''
axios.all([
axios({
baseURL:'',
url:'',
}),
axios({
baseURL:'',
url:'',
})
]).then(axios.spread((res1,res2)=> {
console.log(res1);
console.log(res2);
}))
五、axios实例
查看axios源码你会发现,之前那种使用方式使用的axios是一个全局的实例,如果现在项目不是从同一个服务器请求数据,或者是某些请求需要的全局配置不同了,这个时候就应该针对不同的服务器创建出一个单独的axios实例对象。
export interface AxiosStatic extends AxiosInstance {
create(config?: AxiosRequestConfig): AxiosInstance;
Cancel: CancelStatic;
CancelToken: CancelTokenStatic;
isCancel(value: any): boolean;
all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
}
declare const Axios: AxiosStatic;
export default Axios;
创建axios实例
const instance1 = axios.create({
baseURL:''
})
axios.all([
instance1({
url:'',
}),
instance1({
url:'',
})
]).then(axios.spread((res1,res2) => {
console.log(res1);
console.log(res2);
}))
需要注意:创建出来的axios实例中是没有create,all,spread这些方法的,因为这些方法是定义在AxiosStatic接口中的,而创建出来的axios实例是实现了AxiosInstance接口而已。所以创建出来的实例只能拿来发送请求,执行AxiosInstance能执行的一些操作。
六、网络请求模块的封装
在使用一些第三方的框架的时候,和这个框架直接依赖的文件越少越好,如果是你所有的vue组件中都是通过导入这个axios框架进行网络请求的话,如果有一天这个axios不再维护了,或者出现了重大BUG,那基本就凉凉了,得翻来翻去,把所有用到这个框架的文件都得替换成其它框架。这是一件可怕的事情,工作量巨大,而且如果有一天axios被淘汰了,出现了更好的网络请求框架,那么你的项目也很难进行升级。
所以最好把网络请求作为一个模块,自己先对他进行一层封装,然后自己的业务模块面向自己封装的网络请求模块进行网络请求,这样的话就很灵活了,如果有一天axios淘汰了,那就换一个封装的模块就好了。
在src下创建一个network文件夹,然后在里面放相关封装axios框架的代码
request.js
import axios from 'axios'
//创建实例,给每个服务器创建一个实例,针对这个服务器发送网络请求
const instance1 = axios.create({
baseURL:'http://222.111.333.777:8080',
timeout:5000
})
export function request(config) {
return instance1(config)//instance1()会返回一个promise对象
}
就这样简单封装一下就能解决上面那种可怕的问题,之后使用axios框架的时候这样使用就可以了。
<script>
import {request} from '@/network/request'
export default {
name: 'App',
data() {
return {
goodsData:{}
}
},
created() {
request({
url:'home/goodsData',
params: {
type: 'pop',
page: 1
}
}).then(res => {
this.goodsData = res.data
})
},
}
</script>
七、axios的拦截器
这个东西就跟java中的filter一样,就是可以将请求和响应结果进行一层过滤,过滤掉恶意请求,或者是进行一些操作再发过去请求和响应。
export function request(config) {
instance1.interceptors.request.use(config => {
console.log(config);
return config;//把请求放过去
},err => {//请求失败,请求都没发出去
console.log(err);
})
instance1.interceptors.response.use(res => {
console.log(res);
return res;//把响应放过去
},err => {//响应失败,比如说响应时间过长
console.log(err);
})
return instance1(config)//instance1()会返回一个promise对象
}