之前項目的axios數據請求基本都是寫在各組件方法內,如項目接口變動要修改url地址等參數會比較為麻煩,不易維護,決定對axios進行封裝並將接口統一管理。
一、新建函數文件:
在vue-cli工程內新建axios-request.js、axios-api.js,其中aixos-request.js用於對axios進行封裝,axios-api.js用於接口的統一管理,兩個的文件位置根據自身的工程目錄來定,我的是存放在src文件夾下的axios文件夾內。
二、對axios進行封裝:
// axios-request.js import Vue from 'vue' import Toast from 'muse-ui-toast' /* 引入muse-ui的Toast插件 */ import axios from 'axios' import qs from 'qs' /* 引入qs依賴包,對傳參數據序列化 */ Vue.use(Toast, { time: 5000 /* 設置Toast顯示5s,防止用戶沒有注意到 */ }) /* 創建axios實例 */ const axiosService = axios.create({ baseURL: process.env.API_HOST, /* 在config/dev.evn.js、prod.evn.js里面進行配置 */ timeout: 5000 /* 設置超時時間為5s */ }) /* request攔截器 ==> 對請求參數進行處理 */ axiosService.interceptors.request.use( config => { config.method === 'post' ? config.data = qs.stringify({...config.data}) : config.params = {...config.params} /* 判斷method是否為post,為post則對參數進行序列化,不為post擇不進行序列化 */ config.headers['Content-Type'] = 'application/x-www-form-urlencoded' return config }, error => { Toast.error('錯誤,請重新操作...') Promise.reject(error) }) /* respone攔截器 ==> 對響應做處理 */ axiosService.interceptors.response.use( response => { if (response.data) { return response.data } else { Toast.error('數據錯誤,請重試...') } }, error => { /* 判斷error的status代碼,並將對應的信息告知用戶 */ let text = '' let err = JSON.parse(JSON.stringify(error)) if (err.response.status) { switch (error.response.status) { case 400: text = '請求錯誤(400),請重新申請' break case 401: text = '登錄錯誤(401),請重新登錄' return this.$router.replace('/Login') case 403: text = '拒絕訪問(403)' break case 404: text = '請求出錯(404)' break case 408: text = '請求超時(408)' break case 500: text = '服務器錯誤(500),請重啟軟件或切換功能頁!' break case 501: text = '服務未實現(501)' break case 502: text = '網絡錯誤(502)' break case 503: text = '服務不可用(503)' break case 504: text = '網絡超時(504)' break case 505: text = 'HTTP版本不受支持(505)' break default: text = '網絡連接出錯' } } else { text = '連接服務器失敗,請退出重試!' } Toast.error(text) return Promise.reject(error) } ) /* 將寫好的axios實例暴露出去 */ export default axiosService
如果后台需要前端發送時攜帶token,應在axiosService.interceptors.request.use的config內增加相關內容,我的項目中沒有運用到token,簡單的形式參考下面的代碼:
1 if (store.state.token) { // 判斷是否存在token,如果存在的話,則每個http header都加上token 2 config.headers.Authorization = `token ${store.state.token}`; 3 }
三、對接口進行統一管理:
// axios-api.js import axiosService from './axios-request' /* 從axios-request.js內引入axiosService */ /* 下面是POST形式 */ export const userLogin = data => { return axiosService({ url: '/XXXX/user/xxxx', /* 根據實際接口地址來寫 */ method: 'post', data }) } /* 下面是GET形式 */ export const userInfo = params=> { return axiosService({ url: '/XXXX/user/XXXXX.action', method: 'get', params }) }
這里要注意下,post參數放在data內,get參數放在params內!
四、在組件內使用寫好的接口:
下面是根據我的工程寫的一個登錄接口,僅供參考:
1 import { userLogin } from '../../axios/axios-api' /* 引入登錄接口函數 */ 2 methods: { 3 async login () { 4 this.loginLoading = true 5 let userName = this.userName 6 let passWord = this.passWord 7 let params = { 8 username: userName, 9 password: passWord 10 } 11 if (!userName || !passWord) { 12 this.loginLoading = false 13 this.$toast.error('賬號或密碼不能為空') 14 } else { 15 if ((userName.length < 51) && (passWord.length < 51)) { 16 let res = await userLogin(params) 17 this.loginBack(res) 18 } else { 19 this.loginLoading = false 20 this.$toast.error('賬號或密碼輸入字符不能超過50位') 21 } 22 } 23 }, 24 loginBack (res) { 25 let resBack = res.Back 26 let resData = res.Data 27 if (resBack === '1') { 28 ...... 29 } else { 30 ...... 31 } 32 } 33 }
使用這種方式,需要注意的是方法內的函數需要時用: async await格式;
當然也可以不將接口統一管理而只用axios封裝在組件內寫函數:
1 import axiosService from '../../../../axios/axios-request' /* 這里直接引入axios封裝 */ 2 3 methods: { 4 submitInfo () { 5 let userName = localStorage.getItem('xyz') 6 let dkId = this.nowLand.id 7 let water = this.nowLand.water 8 let status = this.nowLand.status 9 let params = { 10 usename: userName, 11 dkid: dkId, 12 appwater: water 13 } 14 this.$confirm('是否提交申請?', '提示', { 15 type: 'warning' 16 }).then(({ result }) => { 17 if (result) { 18 if (status === 0) { 19 ...... 20 } else { 21 axiosService({ 22 url: '/HPGQ/waterrecord/addWaterRecord.action', 23 method: 'post', 24 params 25 }).then(this.applyBack) 26 } 27 } else { 28 ...... 29 } 30 }) 31 }, 32 applyBack (res) { 33 ...... 34 } 35 }
以上是個人所用的封裝方式,如有錯誤之處歡迎留言指正~~