1. 網(wǎng)絡(luò)請(qǐng)求的方式
發(fā)送網(wǎng)絡(luò)請(qǐng)求的方式有很多種,到目前為止,我們已經(jīng)學(xué)過(guò)了原生ajax,jquery
中的ajax,等諸多網(wǎng)絡(luò)請(qǐng)求的方式,那么在未來(lái)我們vue
的項(xiàng)目中我們?cè)撊绾尉駬衲?/p>
先來(lái)分析一下不同的ajax請(qǐng)求,了解使用與否的理由
1.1 原生Ajax
原生ajax是基于XMLHttpRequest(XHR)
封裝的.
我們都知道原生的ajax不但有兼容問(wèn)題,而且配置很調(diào)用都非呈钊校混亂, 這也是我們不使用的理由
1.2 jquery中的ajax
這個(gè)之前也提到過(guò)這類(lèi)問(wèn)題, jquery
的ajax相對(duì)于原生的ajax來(lái)說(shuō)非常好用, 但是jquery
的ajax是嵌入在真?zhèn)€jquery
中的,因此如果我們要使用jquery
的ajax,就需要引入整體的jquery
但是在咱們Vue
項(xiàng)目的整個(gè)開(kāi)發(fā)過(guò)程中都不需要在使用jquery
,只為了用一個(gè)ajax,引入整體的jquery
, 得不償失.因此在vue
中也不選用jquery
的ajax
1.3 Vue 在1.X版本是推出的Vue-resource插件
Vue-resource
相較于jquery
要輕量很多, 但是Vue
從2.X以后就表示不再更新維護(hù)了, 如果使用它處理ajax請(qǐng)求,未來(lái)代碼的維護(hù)上,是有很大的安全隱患的, 包括現(xiàn)在vue
官網(wǎng)也不推薦你是用Vue-resource
處理ajax
Vue
官網(wǎng)推薦使用axios
處理ajax
1.4 axios 請(qǐng)求
axios
有何優(yōu)點(diǎn),讓vue
官網(wǎng)棄用自家的請(qǐng)求方式,推薦用戶(hù)用axios
呢
那么axios
的優(yōu)點(diǎn)是什么,往下看
除了以上數(shù)據(jù)請(qǐng)求方式外,還有包括fetch
,jsonp
等很多方式幫我們處理數(shù)據(jù)請(qǐng)求
2.axios請(qǐng)求了解與基本使用
2.1 axios 請(qǐng)求的特點(diǎn)
- 支持node端和瀏覽器端: 同樣的API和措,node和瀏覽器全支持别智,平臺(tái)切換無(wú)壓力
- 支持 Promise: 使用Promise管理異步多搀,告別傳統(tǒng)callback方式
- 豐富的配置項(xiàng): 支持請(qǐng)求和響應(yīng)的攔截, 提前處理請(qǐng)求和響應(yīng)數(shù)據(jù)
2.2 axios 使用
2.2.1 下載安裝axios包
$ npm install axios
2.2.2 引入使用axios
// 引入包
import axios from "axios"
2.2.3 發(fā)送基本的請(qǐng)求
// 使用axios
axios({
url:"https://api.github.com/users"
}).then(result => {
console.log(result);
})
示例中,我們并沒(méi)有請(qǐng)求類(lèi)型, axios
默認(rèn)請(qǐng)求為get請(qǐng)求,
如果希望發(fā)送post等其他方式的 請(qǐng)求, 可以在配置對(duì)象中添加method選項(xiàng)
例如:
// 使用post發(fā)送請(qǐng)求
axios({
url:"https://jsonplaceholder.typicode.com/posts",
method: "post"
}).then(result => {
console.log(result);
})
2.2.4 配置對(duì)象中指定get請(qǐng)求參數(shù)
我們可以像傳統(tǒng)get請(qǐng)求傳參一樣在url
路徑后拼接請(qǐng)求數(shù)據(jù).
例如:
axios({
url:"https://jsonplaceholder.typicode.com/posts?userId=1",
}).then(result => {
console.log(result);
})
也可以將get的請(qǐng)求數(shù)據(jù)放在axios
的配置對(duì)象中
例如: 將get請(qǐng)求數(shù)據(jù)放在配置對(duì)象的params
選項(xiàng)中
axios({
url:"https://jsonplaceholder.typicode.com/posts",
params:{
userId: 1
}
}).then(result => {
console.log(result);
})
3. axios 請(qǐng)求方式
axios(config)
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.options(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]]
上面基本的示例中,我們是在axios()
請(qǐng)求的配置對(duì)象中配置請(qǐng)求方式,axios
也提供了通過(guò)不同的方式發(fā)送請(qǐng)求
指定了請(qǐng)求方式發(fā)送請(qǐng)求說(shuō)明
第一個(gè)參數(shù)將是發(fā)送的
url
,第二個(gè)參數(shù)是請(qǐng)求的配置對(duì)象,可以省略,使用默認(rèn)配置
示例:
不是用配置對(duì)象
axios.get("https://jsonplaceholder.typicode.com/posts?userId=1")
.then(result => {
console.log(result);
})
使用配置對(duì)象
axios.get("https://jsonplaceholder.typicode.com/posts",{
params:{
userId:1
}
}).then(result => {
console.log(result);
})
4 處理并發(fā)請(qǐng)求
4.1 axios.all 方法處理并發(fā)請(qǐng)求
有的時(shí)候,我們可能需要同時(shí)發(fā)送兩個(gè)請(qǐng)求,需要兩個(gè)結(jié)果都返回了在進(jìn)行數(shù)據(jù)處理
axios
提供了一個(gè)all
方法幫我們處理并發(fā)請(qǐng)求,使用方式和promise
的all
方法使用類(lèi)似,出入數(shù)組
例如:
axios.all([
axios.get("https://jsonplaceholder.typicode.com/posts"),
axios.post("https://jsonplaceholder.typicode.com/posts")
]).then(resultes => {
console.log(resultes);
})
數(shù)據(jù)結(jié)果:
4.2 取出數(shù)組中的數(shù)據(jù)
通過(guò)示例,并發(fā)請(qǐng)求返回的結(jié)果是一個(gè)數(shù)組,數(shù)組中包裹不同請(qǐng)求的結(jié)果,
如果把數(shù)據(jù)從數(shù)組中取出,我們可能會(huì)有如下的方法
1.通過(guò)下標(biāo)取值
axios.all([
axios.get("https://jsonplaceholder.typicode.com/posts"),
axios.post("https://jsonplaceholder.typicode.com/posts")
]).then(resultes => {
// 通過(guò)索引拿到不同的數(shù)據(jù)
let resutl1 = resultes[0];
let resutl2 = resultes[1];
console.log(resutl1);
console.log(resutl2);
})
2.或者使用解構(gòu)取值
axios.all([
axios.get("https://jsonplaceholder.typicode.com/posts"),
axios.post("https://jsonplaceholder.typicode.com/posts")
]).then(([resutl1,resutl2]) => {
// 通過(guò)解構(gòu)取數(shù)據(jù)
console.log(resutl1);
console.log(resutl2);
})
以上兩種方法都可以取出數(shù)據(jù)
同樣axios
也提供了一個(gè)spread
方法把數(shù)據(jù)從數(shù)組中取出
axios.all([
axios.get("https://jsonplaceholder.typicode.com/posts"),
axios.post("https://jsonplaceholder.typicode.com/posts")
]).then(axios.spread((resutl1,resutl2) => {
// 通過(guò)axios的spread方法取出數(shù)據(jù)
console.log(resutl1);
console.log(resutl2);
}))
4.3 axios.all 方法的問(wèn)題
axios
的all
方法和promise
的all
方法都有一個(gè)致命的缺點(diǎn),就是一點(diǎn)有一個(gè)請(qǐng)求出現(xiàn)錯(cuò)誤,那么整個(gè)請(qǐng)求都會(huì)出現(xiàn)錯(cuò)誤.
但是axios
的all
方法比promise
的好處就是,正常來(lái)說(shuō)服務(wù)器都是連接正常,如果沒(méi)有請(qǐng)求到數(shù)據(jù)也會(huì)返回成功的請(qǐng)求
就算沒(méi)有拿到數(shù)據(jù),本地和服務(wù)器之間的連接也是成功的,只不過(guò)服務(wù)器返回的是其實(shí)數(shù)據(jù)獲取錯(cuò)誤的信息并不是數(shù)據(jù)
無(wú)論如何,在使用時(shí),要注意.
5 axios 請(qǐng)求配置
下面這些是創(chuàng)建請(qǐng)求時(shí)可以用的配置選項(xiàng)。只有 url
是必需的。如果沒(méi)有指定 method
,請(qǐng)求將默認(rèn)使用 get
方法。
5.1 常用配置選項(xiàng)
{
// `url` 是用于請(qǐng)求的服務(wù)器 URL
url: '/user',
// `method` 是創(chuàng)建請(qǐng)求時(shí)使用的方法
method: 'get', // default
// `baseURL` 將自動(dòng)加在 `url` 前面枫甲,除非 `url` 是一個(gè)絕對(duì) URL。
// 它可以通過(guò)設(shè)置一個(gè) `baseURL` 便于為 axios 實(shí)例的方法傳遞相對(duì) URL
baseURL: 'https://some-domain.com/api/',
// `params` 是即將與請(qǐng)求一起發(fā)送的 URL 參數(shù)
// 必須是一個(gè)無(wú)格式對(duì)象(plain object)或 URLSearchParams 對(duì)象
params: {
ID: 12345
},
// `data` 是作為請(qǐng)求主體被發(fā)送的數(shù)據(jù)
// 只適用于這些請(qǐng)求方法 'PUT', 'POST', 和 'PATCH'
// 在沒(méi)有設(shè)置 `transformRequest` 時(shí)扼褪,必須是以下類(lèi)型之一:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - 瀏覽器專(zhuān)屬:FormData, File, Blob
// - Node 專(zhuān)屬: Stream
data: {
firstName: 'Fred'
},
// 'proxy' 定義代理服務(wù)器的主機(jī)名稱(chēng)和端口
// `auth` 表示 HTTP 基礎(chǔ)驗(yàn)證應(yīng)當(dāng)用于連接代理想幻,并提供憑據(jù)
// 這將會(huì)設(shè)置一個(gè) `Proxy-Authorization` 頭,覆寫(xiě)掉已有的通過(guò)使用 `header` 設(shè)置的自定義 `Proxy-Authorization` 頭话浇。
proxy: {
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// `transformRequest` 允許在向服務(wù)器發(fā)送前脏毯,修改請(qǐng)求數(shù)據(jù)
// 只能用在 'PUT', 'POST' 和 'PATCH' 這幾個(gè)請(qǐng)求方法
// 后面數(shù)組中的函數(shù)必須返回一個(gè)字符串,或 ArrayBuffer幔崖,或 Stream
transformRequest: [function (data, headers) {
// 對(duì) data 進(jìn)行任意轉(zhuǎn)換處理
return data;
}],
// `transformResponse` 在傳遞給 then/catch 前食店,允許修改響應(yīng)數(shù)據(jù)
transformResponse: [function (data) {
// 對(duì) data 進(jìn)行任意轉(zhuǎn)換處理
return data;
}],
// `headers` 是即將被發(fā)送的自定義請(qǐng)求頭
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `timeout` 指定請(qǐng)求超時(shí)的毫秒數(shù)(0 表示無(wú)超時(shí)時(shí)間)
// 如果請(qǐng)求話費(fèi)了超過(guò) `timeout` 的時(shí)間渣淤,請(qǐng)求將被中斷
timeout: 1000,
}
5.2 常用配置示例
axios.all([
axios({
baseURL:"https://jsonplaceholder.typicode.com" ,
url: "/posts",
}),
axios({
baseURL:"https://jsonplaceholder.typicode.com" ,
url:"/posts/1"
})
]).then(axios.spread((resutl1,resutl2) => {
// 通過(guò)axios的spread方法取出數(shù)據(jù)
console.log(resutl1);
console.log(resutl2);
}))
每次發(fā)送請(qǐng)求都可以配置當(dāng)前發(fā)送的內(nèi)容
5.3 全局配置
前面講的配置都在在每次發(fā)送請(qǐng)求前進(jìn)行的配置,如果每次發(fā)送都需要用到一些相同的配置,那么我們就可以將這些配置提取出來(lái)成為全局配置
5.3.1 全局配置的方法
// 全局配置基本路徑
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com"
// 全局配置請(qǐng)求頭
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
一但全局配置,那么每次發(fā)送請(qǐng)求都會(huì)使用全局的配置
5.3.2 使用全局配置修改上面的示例
// 全局配置基本路徑
axios.defaults.baseURL="https://jsonplaceholder.typicode.com"
// 發(fā)送的兩次請(qǐng)求都會(huì)使用全局配置的路徑
axios.all([
axios({
url: "/posts",
}),
axios({
url:"/posts/1"
})
]).then(axios.spread((resutl1,resutl2) => {
// 通過(guò)axios的spread方法取出數(shù)據(jù)
console.log(resutl1);
console.log(resutl2);
}))
使用全局配置依然可以正常獲取數(shù)據(jù)
6. axios 實(shí)例
6.1 為什么要?jiǎng)?chuàng)建axios實(shí)例
隨著項(xiàng)目的復(fù)雜度的提升,需要的數(shù)據(jù)量就會(huì)越來(lái)越多,出于服務(wù)器性能的考慮, 可能會(huì)將數(shù)據(jù)部署在多臺(tái)服務(wù)器上,
此時(shí)單單只配置一個(gè)全局baseURL
以及沒(méi)法滿(mǎn)足我們的需求,
此時(shí)需要使用axios
實(shí)例,分別配置對(duì)于不同服務(wù)器數(shù)據(jù)的請(qǐng)求
6.2 創(chuàng)建axios實(shí)例
axios
提供了一個(gè)create方法創(chuàng)建實(shí)例
語(yǔ)法格式如下:
const instance = axios.create(config);
// config為當(dāng)前實(shí)例的配置對(duì)象
6.3 axios 實(shí)例的示例
通過(guò)axios
向不同的服務(wù)器獲取數(shù)據(jù)
// axios實(shí)例一
// instance 向 jsonplaceholder 發(fā)送請(qǐng)求
const instance = axios.create({
baseURL: "https://jsonplaceholder.typicode.com"
})
instance({
url:"/posts"
}).then(res => {
console.log(res);
})
// axios 實(shí)例二
// instance2 向 github 發(fā)送請(qǐng)求
const instance2 = axios.create({
baseURL: "https://api.github.com/users"
})
instance2({
url:"/mojombo"
}).then(res => {
console.log(res);
})
7. axios 封裝
7.1 為什么要對(duì) axios 進(jìn)行封裝
axios
封裝原因說(shuō)明
- 如果不分裝
axios
,就在所有需要數(shù)據(jù)的組件中通過(guò)axios
發(fā)送請(qǐng)求 - 如果未來(lái)需要更換請(qǐng)求的第三方庫(kù),就需更換所有導(dǎo)入
axios
庫(kù)的組件, - 如果
axios
請(qǐng)求出現(xiàn)問(wèn)題,需要調(diào)整,就需要在所有使用了axios
的組件中進(jìn)行調(diào)整,不利于后期維護(hù)
因此我們需要對(duì)axios
進(jìn)行封裝,
這樣所有需要發(fā)送請(qǐng)求的組件都只要使用我們封裝的模塊就可以了,
如果后期需要調(diào)整就只需要修改我們封裝的模塊就可以了
7.2 封裝axios 代碼
import axios from 'axios';
export function request(config){
const instance = axios.create({
baseURL: "https://api.github.com/users"
})
return instance(config)
}
8. axios 全局?jǐn)r截器
axios
在每一個(gè)請(qǐng)求配置中都有一個(gè)配置項(xiàng)用于攔截請(qǐng)求或響應(yīng)結(jié)果
這個(gè)攔截請(qǐng)求只能攔截當(dāng)前配置的請(qǐng)求. 如果我們希望攔截所有的請(qǐng)求,就需要使用全局?jǐn)r截器
全局?jǐn)r截器是會(huì)攔截所有的請(qǐng)求或響應(yīng)
攔截器:就是在請(qǐng)求或響應(yīng)被 then
或 catch
處理前攔截它們。
// 添加請(qǐng)求攔截器
axios.interceptors.request.use(function (config) {
// 在發(fā)送請(qǐng)求之前做些什么
return config;
}, function (error) {
// 對(duì)請(qǐng)求錯(cuò)誤做些什么
return Promise.reject(error);
});
// 添加響應(yīng)攔截器
axios.interceptors.response.use(function (response) {
// 對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么
return response;
}, function (error) {
// 對(duì)響應(yīng)錯(cuò)誤做點(diǎn)什么
return Promise.reject(error);
});
9. 配置的優(yōu)先級(jí)
通過(guò)上面的學(xué)習(xí),知道了axios
的配置有以下這些
- 默認(rèn)配置,自帶的
- 全局配置:
axios.defaults.baseURL=""
- 實(shí)例配置:
axios.create({baseURL:""})
- 發(fā)送請(qǐng)求配置:
axios({baseURL:""})
這些配置的優(yōu)先級(jí)為
配置以一個(gè)優(yōu)先順序進(jìn)行合并吉嫩。這個(gè)順序是:
在
lib/defaults.js
找到的庫(kù)的默認(rèn)值价认,然后是全局
defaults
配置然后是實(shí)例的
defaults
屬性,最后是請(qǐng)求的
config
參數(shù)自娩。后者將優(yōu)先于前者用踩。