2023-01-16
Vue3 使用 Vite 整合 axios 攔截器與 axios proxy
Vue
2022.05.19
這兩天重構了 Vue 3 設定 axios 的攔截器,此外因為 vuex 也有打 API,所以重構的時候,也順便加入 vuex。
攔截器可以當成是一份能帶著走的 code snippet,所以把語法記在部落格裡,以後有開新專案就能照著參考啦 XD
2022.05.25:更新 development 以及 production 的相關設定
我在開發的時候需要處理 API 的跨域問題,所以新增了兩個 .env
環境變數檔:
# 此為開發用的環境變數,檔名後面加上 .local 表示不會進 git NODE_ENV=development VUE_APP_API=/api
# 此為正式版用的環境變數 VUE_APP_API=https://API位置
如果使用 .local
結尾,就會被 git 忽略不會 push,所以我蠻推薦這個做法。以下是檔名與相應的介紹,資料來源為 Vue CLI 官方網站
.env # 在所有的環境中被載入 .env.local # 在所有的環境中被載入,但會被 git 忽略 .env.[mode] # 只在指定的模式中被載入 .env.[mode].local # 只在指定的模式中被載入,但會被 git 忽略
我原本在 proxy 是直接設定 '/api'
這個網址去做 pathRewrite
,但因為正式版會忽略 proxy 設定,導致我的 axios 網址會出現 '/api'
位置,因此我這邊有做一些調整,把 '/api'
改成環境變數去動態決定。
module.exports = { devServer: { proxy: { [process.env.VUE_APP_API]: { target: API 位置, changeOrigin: true, secure: false, pathRewrite: { '^/api': '' } }, } } }
- store/ - index.js - axios/ - api.js ## 管理 api - http.js ## 設定攔截器
記得先安裝 axios 套件:
$ npm install axios
裝好 axios 套件後,我們需要做 axios 的攔截器,以及管理 api 網址,因此我會將目錄結構設計如下:
專案的運作模式為,使用者登入確認後會得到一組 token,登入後的所有 API 行為都會帶這組 token,所以我把 token 寫在攔截器裡。
import axios from 'axios' const $http = axios.create({ baseURL: process.env.VUE_APP_API }) // 攔截請求 $http.interceptors.request.use(config => { const token = localStorage.getItem('token') config.headers.Authorization = `Bearer ${token}` return config }, error => { return Promise.reject(error) }) // 攔截回應 $http.interceptors.response.use(res => { switch (res.status) { case 200: return Promise.resolve(res) default: console.log(res.status) } }, error => { if (error && error.response) { switch (error.response.status) { case 400: console.error(error.response) break case 401: console.error(error) break default: console.error('攔截錯誤請求', error.response.status) return Promise.reject(error) } } }) export default $http
因為 api 數量眾多,所以也集中在一個檔案統一管理 ( 如果數量不多,直接寫在 http.js
,也是個不錯的方法 )
export default { article: { list: 'list/article', chart: 'execute/checkPost', location: 'list/article/1', }, user: { list: 'list/user', detail: 'detail/user' } }
provide
以及 inject
是 Vue 3.0 的新語法,可以取代 Vue.prototype
作為全域引入。
而除了 provide
/ inject
以外,也可以使用 globalProperties
,不過官方好像比較推薦前者做法,有興趣深究的朋友可以深入了解官方 provide / inject 的分享。
接著,我們就使用 provide
, inject
來設定全域引入吧!
以 Vue Cli 為例,打開 main.js,匯入檔案後再使用 provide
傳遞資料:
import http from './axios/http' import api from './axios/api' app.provide('http', http) app.provide('api', api)
接著開啟任一元件檔,用 inject
接收資料後,就能呼叫 API 了。
<script> import { inject } from 'vue' export default { setup () { const api = inject('api') const $http = inject('http') const getData = () => { $http.post(`/${api.article.list}`).then((res) => { console.log('hello world') }) } } } </script>
import $http from '@/axios/http' import api from '@/axios/api' export default createStore({ actions: { getData (context, item) { $http.post(`/${api.article.list}/${item}`).then((res) => { console.log('hello world') }) } } })
覺得自己在用 Vuex 使用攔截器這部分,還沒有辦法處理得很精簡。
像是 $http
以及 api
檔案都需要再重新 import
一次,可能等以後經驗更足了再重新重構看看吧 XD。
以上,如果有任何問題,或是建議的寫法,都歡迎留言告訴我唷,謝謝!
感覺 console.log(‘攔截錯誤請求’, error.response.status) 可以改成
console.error(‘攔截錯誤請求’, error.response.status)
會比較符合語意
真的欸!我再來調整一下,感謝 XD