一、axios的基本使用
例子中使用到的url僅作為示例,不一定有效,想要復現代碼需要使用能夠提供數據的有效服務器接口url
1.1.什么是axios
axios:ajax i/o system;是用於在Vue.js中發送網絡請求的第三方框架;
可通過許多方式發送網絡請求比如:
- 選擇一:傳統的Ajax,配置和調用方式十分混亂,不推薦;
- 選擇二:jQuery-Ajax,基於jQuery框架,不適合在Vue.js中使用;
- 選擇三:官方在Vue1.x時推出的Vue-resource,由於官方不再維護,不推薦;
- 最佳選擇:Vue.js作者尤雨溪推薦的axios,具有非常多的優點,使用起來也十分方便。
1.2.安裝axios
想要使用axios首先要在node中安裝axios,由於運行時依賴axios,所以采用‘--save’的安裝方式。
npm install axios --save
1.3.axios的基本使用
//首先要引入
import axios from 'axios'
//1.最基本的使用方式,method表示請求數據的方法,res為請求到的數據,可在then()中處理。(url僅為示例,表示的服務器接口並不一定存在)
axios({
url: 'http://123.207.32.32:8000/home/multidata',
method: 'get'
}).then(res => {
console.log(res);
})
//2.進行參數拼接
axios({
url: 'http://123.207.32.32:8000/home/data',
// 專門針對get請求的參數拼接
params: {
type: 'pop',
page: 1
}
}).then(res => {
console.log(res);
})
1.4.axios發送並發請求
以下為使用全局的axios和對應的配置進行網絡請求,其中的url都要拼接上baseURL。這種方式只能向固定的服務器接口地址'http://123.207.32.32:8000' 請求數據,不能滿足向不同的分布式服務器請求數據的需求。
//定義全局的baseURL和請求時間timeout
axios.defaults.baseURL = 'http://123.207.32.32:8000'
axios.defaults.timeout = 5000
//使用axios.all()進行並發的數據請求,同樣使用then()處理請求到的數據
axios.all([axios({
url: '/home/multidata'
}), axios({
url: '/home/data',
params: {
type: 'sell',
page: 5
}
})])
.then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))
1.5.創建axios實例請求數據
通過創建axios實例,每一個被創建的實例都有各自的配置,可以向不同ip地址的服務器請求數據,彼此互不干擾。
//創建第一個axios實例:instance1
const instance1 = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//實例instance1可單獨的向服務器請求數據並進行處理
instance1({
url: '/home/multidata'
}).then(res => {
console.log(res);
})
//也可以采用拼接參數的方式請求數據,實例instance1擁有自己的配置
instance1({
url: '/home/data',
params: {
type: 'pop',
page: 1
}
}).then(res => {
console.log(res);
})
// 如果有其他請求可以再創建一個axios的實例:instance2,這樣就可以向其他ip地址的服務器接口請求數據了
const instance2 = axios.create({
baseURL: 'http://222.111.33.33:8000',
timeout: 10000,
// headers: { }//還可以根據需要配置對應的headers
})
二、axios的應用
2.1.不規范的寫法
在組件App.vue中按如下方式請求數據,並進行展示:
<template>
<div id="app">
<!-- 打印請求到的數據 -->
<div>{{result}}</div>
</div>
</template>
<script>
// 引入axios
import axios from 'axios'
export default {
name: 'App',
components: {
},
data(){
return {
// 對請求來的數據進行處理(這里省略)
result:''
}
},
//生命周期函數created():在Vue實例創建的時候就調用。在這里實現,Vue實例一創建便發送數據請求
created(){
axios({
url: 'http://123.207.32.32.:8000/api/home/multidate'
}).then(res => {
console.log(res);
// 將請求到的數據res存儲到data中
this.result = res;
})
}
}
</script>
<style>
</style>
雖然這種方法也可以正常請求到數據,但是,如果每一個組件都使用這種方式請求數據,就會對第三方框架axios產生過度的依賴。一旦axios框架不再維護或出現重大bug不再修復,想要在原有項目中去除對第三方框架axios的依賴使用其他框架就會變得十分復雜。所以這種請求數據的方式雖可行,但是非常不規范。不符合"高內聚,低耦合"的程序設計思想。
2.2.axios的規范用法
單獨封裝一個axios組件進行數據請求(模塊化思想)。如圖,這樣即使第三方框架axios更改了,只需要修改封裝的組件x即可。所以,當我們使用第三方框架的時候,最好采用這種方式,減小對第三方框架的依賴,便於維護。
首先在,項目目錄的src(源碼)文件夾下新建network文件夾,再在里面新建request.js文件,專門用於放置axios數據請求組件:
以下示例為,在request.js文件中封裝axios數據請求模塊,在main.js中進行數據請求。
方式一:
在request.js中:
//導入第三方框架
import axios from 'axios'
//1.創建axios的實例(不要使用全局的方式)並進行相應配置
/*
為了考慮擴展性,不要用export default 直接導出axios對象。而是一函數形式導出,函數里面可有多個axios實例
傳入三個參數:其中success和failure分別是表示請求成功和失敗后的處理函數,負責把請求到的數據通過回調傳出去
*/
export function request(config, success, failure) {
//該函數的基本配置
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//2.發送真正的網絡請求(在該函數的相同配置下可創建不同的實例);
/*
這里axios實例instance的參數config是在request函數基本配置基礎上的配置:傳入config中的url: '/home',那么加上request函數的基本配置,最后請求數據的url:'http://123.207.32.32:8000/home';相當於request函數確定請求的服務器地址,request函數里的axios實例請求同一服務器上的其他接口(分頁)數據。
*/
instance(config)
.then(res => {
// 通過回調傳入的success函數的方式把請求到的數據傳出去
success(res)
})
.catch(err => {
// 同上
failure(err)
})
}
/* 可傳出包含多個實例的多個函數
export function instance2() {
}
在main.js文件中請求數據:
//導入第三方框架
import axios from 'axios'
// 引入request函數.
import { request } from "./network/request";
//調用request函數,傳入三個參數
request(
// 參數1:config
{
url: '/home/multidata'
},
// 參數2:success函數
/*
補充:如何實現回調?
1.把success函數當作參數傳入request函數;
2.request函數調用傳進來的success函數,並傳入請求到的數據:success(res);
3.success(res)相當於函數調用,回到了這里調用success函數,並成功地把res傳了過來.
*/
res => {
console.log(res);//處理代碼
},
// 參數3:failure函數
err => {
console.log(err);
}
)
方式二:
只給request函數傳入一個參數config:
在request.js中:
// 導入axios框架
import axios from 'axios'
//要求傳入的config中包含success和failure兩個函數
export function request(config) {
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//2.發送真正的網絡請求,config.baseConfig負責傳入各axios實例的配置
instance(config.baseConfig)
.then(res => {
// 通過config調用success函數
config.success(res)
})
.catch(err => {
config.failure(err)
})
}
在main.js文件中請求數據:
// 引入request函數.
import { request } from "./network/request";
//僅傳入一個參數:config對象
request ({
baseConfig: {
// 基本配置
},
success: function(res){
//處理代碼
},
failure: function (err){
//處理代碼
}
})
方式三(更優雅):
上面的兩種方式都是采用回調函數的方式,不夠優雅。更加優雅的方式是采用ES6的Promise實現:
在request.js中:
// 導入axios框架
import axios from 'axios'
export function request(config) {
//在函數中返回一個新建的Promise對象
return new Promise((resolve, reject) => {
//1.發送真正的網絡請求
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//2.發送真正的網絡請求,config.baseConfig負責傳入基本配置
instance(config)
.then(res => {
//通過Promise對象的resolve和reject函數把請求到的數據傳出去
resolve(res)
})
.catch(err => {
reject(err)
})
})
}
在main.js文件中請求數據:
// 引入request函數.
import { request } from "./network/request";
//注意request函數返回了一個Promise對象,所以可以直接.then()進行處理
request({
url: '/home/multidata',
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
方式四(最優雅):
以為就只有上面三種封裝方法?還有對優雅的封裝方式呢:
在request.js中:
export function request(config) {
//1.創建axios實例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000
})
//2.發送真正的網絡請求
// 實際上instance(config)返回的即是一個Promise,不必像方式三一樣在函數中封裝一層Promise並返回出去
return instance(config)
}
在main.js文件中請求數據:
// 引入request函數.
import { request } from "./network/request";
request({
url: '/home/multidata',
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
總結:封裝的方式推薦使用方式四,最靈活也最簡潔。封裝完畢之后,想要發送網絡請求只需要引入並調用request()函數就行了。這樣,即使axios框架不維護了,也只是需要更改request()函數而已,十分利於維護。
三、axios攔截器
axios提供了攔截器,用於在每次發送完請求或者得到響應后,進行對應的處理。
攔截器一共提供了四種攔截:
- 請求成功后攔截
- 請求失敗后攔截
- 響應成功后攔截
- 響應失敗后攔截
在上面封裝好的request.js基礎上添加攔截器:
export function request(config) {
//1.創建axios實例
const instance = axios.create({
baseURL: 'http://123.207.32.32:8000',
timeout: 5000,
// headers:{}
})
/*
2.axios攔截器
axios.interceptors:全局攔截器
局部攔截器(僅攔截instance實例)
use()的兩個參數都為函數
*/
/*
2.1.請求攔截:
成功發出請求時,使用use()第一個參數(函數)處理;
發出請求失敗時,使用use()第而個參數(函數)處理
*/
instance.interceptors.request.use(
//攔截到的時config配置信息
config => {
console.log(config);//打印攔截信息
/*
這里可以對攔截到的信息進行處理
*/
//攔截完config之后一定要返回,不然請求就發不出去了
return config;
},
err => {
console.log(err);
}
);
/*
2.2.響應攔截:
響應成功,使用use()第一個參數(函數)處理;
響應失敗,使用use()第而個參數(函數)處理
*/
instance.interceptors.response.use(
//攔截到的是服務器返回的數據res
res => {
console.log(res);
// 同樣處理完后一定要返回被攔截的結果res,這里只返回res.data即可,因為服務器的響應一般是數據
return res.data;
},
err => {
console.log(err);
}
)
//3.發送真正的網絡請求
return instance(config)
}
在main.js中調用request函數發送網絡請求:
// 引入request函數.
import { request } from "./network/request";
request({
url: '/home/multidata',
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
請求攔截:
可以看到當成功發出請求時,在request.js中的第88行打印了請求攔截的信息就是出傳入的config相關配置。當發送請求失敗時,由use()的第二個參數(函數)打印失敗信息。
響應攔截:
當服務器響應失敗時,由use()的第二個參數(函數)打印失敗信息。
為什么需要請求攔截?/請求攔截的作用
-
當config中的一些信息不符合服務器的要求時。比如修改headers信息,除了可以在創建axios實例時修改時,還可以攔截之后進行修改。
-
當每次發送網絡請求時,都希望在界面中顯示一個請求的圖標。就可以在攔截后通過show()顯示出來,請求成功后,再在相應攔截中進行隱藏。
-
某些網絡請求(比如登錄(token)),必須攜帶一些特殊的信息。