推薦使用Vue-cli工具來創建和管理項目,就算剛開始不熟悉,用著用著便可知曉其中的奧妙。前一段時間官方所推薦的數據請求插件還是
Vue-resource
,但現在已經變了,變成了Axios
,不用知道為什么變了,反正這個用起來比那個好一些,用就是了,下面是一些封裝axios
請求的一些經驗,不對之處,還望多多指教!
#01
創建文件,Vue項目初始化之后,在src
目錄下再創建一個util
工具文件夾,一般就是用來存放一些封裝的函數方法,現在讓我們在util
文件目錄下創建一個http.js
文件,封裝axios
方法。
#02
直接上代碼(常規版),代碼中有詳細的注釋
import axios from 'axios' //引用axios
import {Promise} from 'es6-promise' //引入Promise
// axios 配置
axios.defaults.timeout = 5000; //設置超時時間
axios.defaults.baseURL = 'http://localhost:4000/api/v1/'; //這是調用數據接口
// http request 攔截器(所有發送的請求都要從這兒過一次),通過這個,我們就可以把token傳到后臺,我這里是使用sessionStorage來存儲token等權限信息和用戶信息,若要使用cookie可以自己封裝一個函數并import便可使用
axios.interceptors.request.use(
config => {
const token = sessionStorage.getItem("token"); //獲取存儲在本地的token
config.data = JSON.stringify(config.data);
config.headers = {
'Content-Type':'application/json' //設置跨域頭部,雖然很多瀏覽器默認都是使用json傳數據,但咱要考慮IE瀏覽器。
};
if (token) {
config.headers.Authorization = "Token " + token; //攜帶權限參數
}
return config;
},
err => {
return Promise.reject(err);
}
);
// http response 攔截器(所有接收到的請求都要從這兒過一次)
axios.interceptors.response.use(
response => {
//response.status===401是我和后臺約定的權限丟失或者權限不夠返回的狀態碼,這個可以自己和后臺約定,約定返回某個自定義字段也是可以的
if(response.status == 401) {
router.push({ //push后面是一個參數對象,可以攜帶很多參數,具體可以去vue-router上查看,例如query字段表示攜帶的參數
path: '/login'
})
}
return response;
},
error => {
return Promise.reject(error.response.data)
});
export default axios;
/**
* fetch 請求方法
* @param url
* @param params
* @returns {Promise}
*/
export function fetch(url, params = {}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err)
})
})
}
/**
* post 請求方法
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data = {}) {
return new Promise((resolve, reject) => {
axios.post(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
})
}
/**
* patch 方法封裝
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url, data = {}) {
return new Promise((resolve, reject) => {
axios.patch(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
})
}
/**
* put 方法封裝
* @param url
* @param data
* @returns {Promise}
*/
export function put(url, data = {}) {
return new Promise((resolve, reject) => {
axios.put(url, data)
.then(response => {
resolve(response.data);
}, err => {
reject(err);
})
})
}
#03
(動態版),axios
的攔截器不是必要的,不是每個項目都需要,而且headers
里面的Content-Type
和Authorization
不止一種,這時就需要使用另一種方法。
util/http.js
import axios from 'axios' //引用axios
import {Promise} from 'es6-promise' //引入Promise
// axios 配置和攔截器都不用了,這里我使用了一個動態配置數據請求地址,在App.vue中,代碼在下面,這個也不是必須的。
//^_^下面都設置一個默認的頭部,使用的時候可以傳入數據覆蓋^_^,例如使用fetch(GET)方法時,沒有請求數據,但是請求頭有變化,則應寫成 fetch("地址", {}, {"這里寫頭部的內容"}) 記住沒數據用一個空對象占位置
/**
* fetch 請求方法
* @param url
* @param params
* @returns {Promise}
*/
export function fetch(url, params = {}, headers = {
'Content-Type': 'application/json', //設置跨域頭部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}) {
return new Promise((resolve, reject) => {
axios.get(url, {
params: params,
headers: headers
})
.then(response => {
resolve(response.data);
})
.catch(err => {
reject(err.response)
})
})
}
/**
* post 請求方法
* @param url
* @param data
* @returns {Promise}
*/
export function post(url, data = {}, config = {
"headers": {
'Content-Type': 'application/json', //設置跨域頭部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}
}) {
return new Promise((resolve, reject) => {
axios.post(url, data, config)
.then(response => {
resolve(response.data);
}, err => {
reject(err.response);
})
})
}
/**
* patch 方法封裝
* @param url
* @param data
* @returns {Promise}
*/
export function patch(url, data = {}, config = {
"headers": {
'Content-Type': 'application/json', //設置跨域頭部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}
}) {
return new Promise((resolve, reject) => {
axios.patch(url, data, config)
.then(response => {
resolve(response.data);
}, err => {
reject(err.response);
})
})
}
/**
* put 方法封裝
* @param url
* @param data
* @returns {Promise}
*/
export function put(url, data = {}, config = {
"headers": {
'Content-Type': 'application/json', //設置跨域頭部
"Authorization": 'JWT ' + sessionStorage.getItem("authToken")
}
}) {
return new Promise((resolve, reject) => {
axios.put(url, data, config)
.then(response => {
resolve(response.data);
}, err => {
reject(err.response);
})
})
}
App.vue(這是在
src
目錄下的程序入口文件)
<template>
<div id="app">
<router-view/>
</div>
</template>
<script>
import axios from 'axios';
let protocol = window.location.protocol; //協議
let host = window.location.host; //主機
let reg = /^localhost+/;
if(reg.test(host)) {
//若本地項目調試使用
axios.defaults.baseURL = 'http://10.0.xx.xxx:xxxx/api/';
} else {
//動態請求地址
axios.defaults.baseURL = protocol + "http://" + host + "/api/";
}
axios.defaults.timeout = 30000;
export default {
name: 'app',
axios //這里記得導出,若請求地址永久固定一個,則就按照`普通版`配置一個baserURL就可以了
}
</script>
<style lang="scss"> //這里我使用的是scss
@import '~@/style/style'
</style>
04
總結
-
常見問題
- 在使用動態版時,為什么稱為動態呢,是因為訪問地址和請求地址是同一個地址可端口號,例如我通過
http://www.cmgos.com
(默認端口80)訪問項目,那么我的baseURL
會自動的變為http:www.cmgos.com:80/api/
,這么做的原因是當某一天項目遷移或者http
改為https
時,不用你再去更改請求地址,程序自動就完成了 - 數據請求地址配置不正確?如果你配置了
baseURL
,那么你封裝的函數在使用時僅需傳入基于baseURL
的請求地址,例如傳入login/
那么請求地址會自動變為http:www.cmgos.com:80/api/login/
,若未配置,那么可以直接傳入整個請求地址
- 在使用動態版時,為什么稱為動態呢,是因為訪問地址和請求地址是同一個地址可端口號,例如我通過
-
注意事項
- 在使用動態版時,由于沒有使用攔截器,所以下面封裝的函數在返回錯誤的時候需要寫成
err.response.data
來獲取返回的數據,但我寫的是err.response
,因為這樣可以拿到(status)狀態碼
等信息,若不需要判斷返回的狀態碼,則改為err.response.data
便可
- 在使用動態版時,由于沒有使用攔截器,所以下面封裝的函數在返回錯誤的時候需要寫成
博客地址:http://www.keyup.top