vue.js 整合 axios 並設定 global interceptors 與 toast 訊息
延續 使用 Primevue 製作 Vue 模板 與 Spring Boot Vue Axios 實現前後端分離的跨域訪問(CORS), axios 除了有其兩大特性: Asynchronous JavaScript and XML (ajax) or more modern Asynchronous JavaScript and JSON (ajaj). 以外,還有可以設定 Interceptor for Request and Response。
- 建立客製的 axios.js
在 plugins 目錄下,建置客製的 axios 檔案,在此加入要在送出要求給主機 ( request ) 及 主機回應 (response) 時的中斷檢查
import Vue from 'vue'; import axios from 'axios' axios.defaults.baseURL = "http://your.domain.name/"; // 域名 // Error Handle const errorHandle = (status, msg) => { switch (status) { case 400: console.log("400") this.$toast.add({severity:'warn', summary: 'Bad Request', detail: msg, life: 3000}); break; case 401: console.log("401") Vue.prototype.$toast.add({severity:'warn', summary: '認證失敗', detail: msg , life: 3000}); break; default: break; } } // doing something with the request export const jwtToken = localStorage.getItem("jwtToken"); axios.interceptors.request.use( (request) => { // do something with request meta data, configuration, etc // dont forget to return request object, otherwise your app will get no answer return request; } ); // doing something with the response axios.interceptors.response.use( (response) => { return response; }, (error) => { const {response} = error; if (response) { // 成功發出請求且收到 response, 但有 error errorHandle(response.status, response.data.error); return Promise.reject(error); } else { // 成功發出請求但沒收到 response if (!window.navigator.onLine){ //如果是網路斷線 Vue.prototype.$toast.add({severity:'warn', summary: 'Warn Message', detail: "網路出了問題, 請重新連線", life: 3000}); } else { // 其它問題 Vue.prototype.$toast.add({severity:'warn', summary: 'Warn Message', detail: "主機伺服器發生問題, 請連絡資訊單位", life: 3000}); return Promise.reject(error); } } } ); export default axios
- 在 main.js 加入 axios.js & vue-axios
其中程式碼中 Vue.use(VueAxios, axios)
, 這讓你可以使用 this.axios
or this.$http
… 來作整合
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import i18n from './i18n' import VueAxios from 'vue-axios' import './plugins/primevue.js' import axios from './plugins/axios.js' Vue.use(VueAxios, axios) // 這讓你可以使用 this.axios or this.$http... Vue.config.productionTip = false new Vue({ router, store, i18n, render: h => h(App) }).$mount('#app') i18n.locale = navigator.language;
- 一般 vue.js & axios.js 的作法
一般的作法都是使用 this.$http.post
…後帶網址,但若網址有異動時,所有程式就要重新修正
<template> <div class="loginPage"> <Toast /> <Button icon="pi pi-sign-in" label="Login" @click="btnLogin($event)" class="p-d-block p-m-2" >Login</Button> </div> </template> <script> export default { methods: { async btnLogin() { this.submitted = true; if (this.username && this.password) { let data = {"username" : this.username, "password": this.password}; const token = await this.$http.post('/jwt/login',data).then(res=>res.data.token); if (token){ localStorage.setItem("jwtToken", token); setTimeout(() => { this.$router.push("/"); }, 300); this.blockedDocument = false; } else { localStorage.removeItem("jwtToken"); } this.blockedDocument = false; } }, }, } </script>
- 建議的作法
建立 axios 的 api : SystemApi.js,將所有的 request 寫在 api 裡,統一管理,當有網址異動時,只要修改這裡的網址即可。
import axios from '../plugins/axios.js'; /** 若是要連到其它主機, 則需要另外建立獨立的 instance const authApi = axios.create({ baseURL: "https://other.domain.name/", headers: { "X-REQUEST-TYPE":"axios" } }); */ // User 相關的 api export const apiUserLogin = data => axios.post('/jwt/login', data).then(res=>res.data);
在應用時,呼叫 SystemApi.js 裡的 apiUserLogin 即可。
<template> <div class="loginPage"> <Toast /> <div class="p-field p-fluid"> <div class="p-field p-py-2"> <span class="p-float-label"> <InputText type="text" v-model="username" required="true" autofocus :class="{'p-invalid': submitted && !username}" /> <label for="username">{{ $t('SYSTEM.USER_NAME') }}</label> <small class="p-invalid" v-if="submitted && !username">{{ $t('REQUIRED.USER_NAME') }}</small> </span> </div> <div class="p-field p-py-2"> <span class="p-float-label"> <InputText type="password" v-model="password" required="true" :class="{'p-invalid': submitted && !password}" /> <label for="password">{{ $t('SYSTEM.PASSWORD') }}</label> <small class="p-invalid" v-if="submitted && !password">{{ $t('REQUIRED.PASSWORD') }}</small> </span> </div> </div> <Button icon="pi pi-sign-in" label="Login" @click="Login($event)" class="p-d-block p-m-2" >Login</Button> </div> </template> <script> import {apiUserLogin} from '@/apis/SystemApi.js'; export default { data() { return { username: "", password: "", submitted: false, blockedDocument: false }; }, mounted() { let jwtToken = localStorage.getItem("jwtToken"); if (jwtToken) { this.$router.push("/"); } }, methods: { async Login() { this.submitted = true; if (this.username && this.password) { let data = {"username" : this.username, "password": this.password}; const token = await apiUserLogin(data).then(data=>data.token); if (token){ localStorage.setItem("jwtToken", token); setTimeout(() => { this.$router.push("/"); }, 300); this.blockedDocument = false; } else { localStorage.removeItem("jwtToken"); } this.blockedDocument = false; } }, }, }; </script>
你必須 登入 才能發表評論。