尤雨溪之前在微博發(fā)布消息,不再繼續(xù)維護 vue-resource
,并推薦大家開始使用 Axios
,本文就說一下在 Vue 項目里使用 Axios 配置 JWT 、全局攔截請求、發(fā)送表單數(shù)據(jù)等等。
本文里使用的示例代碼,已測試能正常使用
首先請務(wù)必已仔細閱讀 Axios 文檔并熟悉 JWT:
安裝
npm i axios
npm i es6-promise
為什么要安裝 promise polyfill ?雖然 Axios 的 GitHub 主頁開頭說了支持 IE8,但文檔最下面又「偷偷」說,前提是瀏覽器支持 promise (太雞賊了),如果你不用關(guān)心瀏覽器兼容,那就不用安裝 es6-promise (那你也太幸福了)。
把 Axios 配置成 Vue 插件
用過 vue-resource 的都知道,它本身封裝成了 Vue 插件,可以直接在 Vue 組件里使用 this.$http
, Axios 本身雖然沒有封裝,但我們也可以手動把它封裝成 Vue 插件。
具體原理請看 Vue框架引入JS庫的正確姿勢,下面我就用代碼演示一下:
AxiosPlugin.js↓
require('es6-promise').polyfill() // 引入一次就行
import axios from 'axios'
// 創(chuàng)建 axios 實例
// 這里 export 的原因是方便組件外使用 axios
export const Axios = axios.create({
baseURL: 'xxx',
timeout: 5000,
})
// 將 Axios 實例添加到Vue的原型對象上
export default {
install(Vue) {
Object.defineProperty(Vue.prototype, '$http', { value: Axios })
}
}
main.js↓
import Vue from 'vue'
import AxiosPlugin from 'xxx/xxx/AxiosPlugin'
Vue.use(AxiosPlugin)
使用 axios 示例
在組件內(nèi)部↓↓
// GET 獲取用戶信息
// http://xxxx/user?a=1&b=2
const data = {
params: {
a: 1,
b: 2,
}
}
this.$http.get(url, data).then(res => {
console.log(res)
})
// POST 請求
const data = {
a: 1,
b: 2,
}
this.$http.post(url, data).then(res => {
console.log(res)
})
在組件外部↓↓
// POST
import { Axios } from 'xxx/xxx/AxiosPlugin'
Axios.post(url, data)
以上是 Axios 的基本配置,下面我們說一下如何以 x-www-form-urlencoded 格式發(fā)送表單數(shù)據(jù)、設(shè)置 JWT 的 token 、以及 token 過期自動登錄。
高級配置
廢話不多說,直接上完整的代碼,伸手黨的福利
AxiosPlugin.js↓
require('es6-promise').polyfill()
import axios from 'axios'
export const Axios = axios.create({
baseURL: 'http://xxxxx/',
timeout: 10000,
})
//POST傳參序列化(添加請求攔截器)
// 在發(fā)送請求之前做某件事
Axios.interceptors.request.use(config => {
// 設(shè)置以 form 表單的形式提交參數(shù),如果以 JSON 的形式提交表單,可忽略
if(config.method === 'post'){
// JSON 轉(zhuǎn)換為 FormData
const formData = new FormData()
Object.keys(config.data).forEach(key => formData.append(key, config.data[key]))
config.data = formData
}
// 下面會說在什么時候存儲 token
if (localStorage.token) {
config.headers.Authorization = 'JWT ' + localStorage.token
}
return config
},error =>{
alert("錯誤的傳參", 'fail')
return Promise.reject(error)
})
//返回狀態(tài)判斷(添加響應(yīng)攔截器)
Axios.interceptors.response.use(res =>{
//對響應(yīng)數(shù)據(jù)做些事
if(!res.data.success){
alert(res.error_msg)
return Promise.reject(res)
}
return res
}, error => {
if(error.response.status === 401) {
// 401 說明 token 驗證失敗
// 可以直接跳轉(zhuǎn)到登錄頁面,重新登錄獲取 token
location.href = '/login'
} else if (error.response.status === 500) {
// 服務(wù)器錯誤
// do something
return Promise.reject(error.response.data)
}
// 返回 response 里的錯誤信息
return Promise.reject(error.response.data)
})
export default {
install(Vue) {
Object.defineProperty(Vue.prototype, '$http', { value: Axios })
}
}
main.js↓
import Vue from 'vue'
import AxiosPlugin from 'xxx/xxx/AxiosPlugin'
Vue.use(AxiosPlugin)
Login.vue ↓
export default {
name: 'Login',
data() {
return {
username: '',
password: '',
}
},
methods: {
onLogin() {
const { username, password } = this
const data = {
username,
password
}
this.$http.post('url', data)
.then(res => {
// 登錄成功
if(res.token) {
// 儲存 token
localStorage.token = res.token
}
})
.catch(error => {
// 登錄失敗
// 驗證后端返回的錯誤字段,如果匹配,提示用戶
// axios 配置里必須要 return Promise.reject(error.response.data) 才能拿到錯誤字段
if(error.xxx == 'xxx') {
alert('用戶名或密碼錯誤!')
}
})
}
}
}
以上代碼在好幾個項目里都正常使用,沒有問題
具體還可以參照我寫的一個開源項目
vue-shop
碼字不易,如果對你有用,請支持點贊~謝謝 :)