一個基於vuecli3和vue-admin-template改造的響應式後臺管理系統javascript
後臺系統少不了登錄、註冊、重置密碼功能。雖然說是三個頁面,可是樣式風格統一,因此只用寫一套樣式。這塊內容很少,咱來好好梳理,寫一寫。 先上效果圖html
運用mock來模擬後臺接口能更加便捷高效的進行前端開發,在這裏我只是簡單的模擬後臺接口,返回一些簡單的數據,更多功能能夠參考mockjs官網,寫的很詳細的噢~前端
npm install --save-dev mockjs
複製代碼
import '@/assets/mock' 複製代碼
在assets文件夾下建立mock文件夾,並建立index.jsvue
import Mock from 'mockjs' // 獲取 mock.Random 對象 const Random = Mock.Random // mock一組數據 const loginData = () => { const data = { token: Random.string(10) } return { data: data, resultCode: 1, resultMessage: 'success' } } Mock.mock('/apiReplace/login', 'post', loginData) Mock.mock('/apiReplace/loginByVin', 'post', loginData) 複製代碼
在assets目錄下新建http文件夾,用來存放請求後端接口的一些配置文件。java
後臺的接口地址須要一個文件進行統一的定義,而後全局聲明以後,能夠在項目裏任意使用ios
根目錄新建http/apiUrl.js,定義接口urlgit
/* 全局定義接口url */ // host頭,這裏咱們要使用代理,因此定義的字符串apiReplace是用來進行反向代理時的標記字符串。 const apiHost = '/apiReplace/' // 密碼登陸 const Login = `${apiHost}login` // 短信登陸 const LoginByVin = `${apiHost}loginByVin` export default { Login, LoginByVin } 複製代碼
import Api from '@/assets/http/apiUrl' Vue.prototype.API = Api 複製代碼
這樣咱們就能在項目裏經過this.API.xxx去獲取相應的接口url了github
總所周知,使用axios調用後臺接口時,每次都須要寫這麼長串:npm
當業務邏輯複雜的時候,寫起來會比較繁瑣,後期維護更加不方便,每次都要定位到具體位置去一個個替換修改。因此在axios請求時再封裝一層就顯得尤其重要。element-ui
咱們常常須要在發起請求以前,修改請求頭或者是在接口請求成功以後進行數據的預處理,axios給咱們提供了request和response的攔截器,讓咱們能夠在這裏頭進行一些業務操做。
在http文件夾下新建service.js文件
import axios from 'axios' import { Message } from 'element-ui' import { getToken } from '@/assets/utils/token' import router from '@/router' import store from '@/store' // 建立axios實例 const service = axios.create({ baseURL: process.env.BASE_API, // api 的 base_url timeout: 10000 // 請求超時時間 }) 複製代碼
// request攔截器 service.interceptors.request.use( config => { // 在此處設置請求頭參數 const token = getToken() if (token != null) { config.headers['Authorization'] = token } return config }, error => { // Do something with request error console.log(error) // for debug return Promise.reject(error) } ) 複製代碼
service.interceptors.response.use( response => { return response // 返回請求成功結果,status=200 }, err => { // 請求失敗時,即status!=200 if (err && err.response) { switch (err.response.status) { case 400: err.message = '錯誤請求' break case 401: err.message = '未受權,請從新登陸' break case 403: err.message = '禁止訪問' break case 404: err.message = '請求錯誤,未找到該資源' break case 405: err.message = '請求方法未容許' break case 408: err.message = '請求超時' break case 413: err.message = '上傳文件過大' break case 500: err.message = '服務器端出錯' break case 501: err.message = '網絡未實現' break case 502: err.message = '網絡錯誤' break case 503: err.message = '服務不可用' break case 504: err.message = '網絡超時' break case 505: err.message = 'http版本不支持該請求' break default: err.message = `鏈接錯誤,${err.response.msg}` } } else { err.message = '當前網絡狀態不佳' } Message.closeAll() Message({ message: err.message || '數據解析出錯', type: 'error', customClass: 'errorloginwidth', duration: '3000' }) // 若是是token過時的情況,退出登錄重定向到登錄頁 if (err.response && err.response.status === 401) { store.dispatch('FedLogOut') // 前端登出,移除token router.replace({ path: `/login?redirect=${window.location.href.split(/[#]/g)[1]}` }) } return Promise.reject(err) } ) 複製代碼
export default service 複製代碼
npm install --save-dev qs
複製代碼
直接貼上我定義的文件:
這裏我只定義了一個基本的httpRequest方法,後期若是須要定義併發調用、或者其餘情景下的方法,均可以自行增長。
/* 封裝axios請求 */ /* 用法示例:(*)爲必須參數 this.$request.httpRequest({ headers: false, // 是否格式化參數 (*)method: 'post', // 請求方式,post或get (*)url: this.API.ResetPassword, // 請求地址,請求地址的配置在@/api/apiUrl.js noLoading: true, // 是否顯示全局Loading遮罩,默認每一個請求都顯示遮罩,即默認不設置該參數。若是須要某個請求不加遮罩,就設置noLoading: true便可 returnFullData: true, // 是否返回完整數據,例如接口返回的數據格式爲{ code:0, data: [], meaasge:''},則默認請求成功以後的回調函數的參數爲data:[],若是設置returnFullData: true,則回調參數爲{ code:0, data: [], meaasge:''} hideErrorMsg: true, // 是否展現錯誤提示 (*)params: {}, // 請求參數,object類型 (*)success: (data) => { // 請求成功以後的回調函數,data是回調參數 // 在這裏寫請求成功後的邏輯 }, error: (err) => { 請求不成功以後的回調函數,data是回調參數 // 在這裏寫請求報錯後的邏輯 } }) */ import service from './service' import { Message, Loading } from 'element-ui' import Qs from 'qs' function requestMethods(options) { return new Promise((resolve, reject) => { try { switch (options.method) { case 'post': if (options.headers) { resolve( service({ url: options.url, method: 'post', data: options.params }) ) } else { resolve( service({ url: options.url, method: 'post', data: Qs.stringify(options.params) }) ) } break case 'get': resolve( service({ url: options.url, method: 'get', params: options.params }) ) break default: // 默認是get調用 resolve( service({ url: options.url, method: 'get', params: options.params }) ) break } } catch (e) { Message({ message: 'HTTP請求方法出錯!', type: 'error', duration: 3 * 1000 }) reject('methods error!') } }) } function httpRequest(options = {}) { let loading if (!options.noLoading) { // 啓用全局loading loading = Loading.service({ lock: true, text: '加載中...', spinner: 'el-icon-loading', background: 'rgba(0, 0, 0, 0.7)' }) } requestMethods(options).then(response => { // 成功返回結果的邏輯。根據接口定義的數據返回格式 修改判斷條件 const data = response.data if (data.resultCode === '1' || data.resultCode === 1) { // 成功 const result = options.returnFullData ? data : data.data // 返回完整數據結構仍是隻返回有效數據 options.success(result) } else { if (!options.hideErrorMsg) { // 失敗 let errorMsg = data.hasOwnProperty('resultMessage') ? data.resultMessage : '數據解析錯誤' switch (data.resultCode) { case '401': errorMsg = '暫無操做權限' break } Message.closeAll() Message({ message: errorMsg, type: 'error', customClass: 'errorloginwidth', duration: 3000 }) } options.error(data) } if (!options.noLoading) { // loading完畢 loading.close() } }).catch(e => { options.error(e.response) }) } export default { httpRequest } 複製代碼
import Request from '@/assets/http' Vue.prototype.$request = Request 複製代碼
這樣就能夠在項目中經過this.$request去調用接口啦~ 基礎調用很簡單,只用醬紫:
this.$request.httpRequest({ url: this.API.SendSms, params: {}, success: (data) => { // 在這裏寫成功調用接口後的邏輯 } }) 複製代碼
那複雜的用法這裏貼個例子,完整代碼能夠去看看項目代碼哦,地址我會貼在文章頭。
好比說這個登錄頁面,要獲取手機驗證碼:
點擊發送驗證碼,開始一分鐘倒計時並調用發送短信驗證碼的接口
<!--html部分--> <el-form-item prop="code" class="login-input-item"> <span class="svg-container"> <svg-icon icon-class="password" /> </span> <el-input v-model="loginForm.code" autocomplete="off" type="number" name="code" placeholder="驗證碼" maxlength="4" style="padding-left: 45px" @keyup.enter.native="handleLogin" /> <span :style="{ cursor: isOvertime ? 'default' : 'pointer'}" class="code" @click="sendMessage"> {{ word }} </span> </el-form-item> // js部分 sendMessage() { if (this.isOvertime) { return false // 還在倒計時,不往下執行 } const params = { 'phone': this.loginForm.phoneNumber } if (!params.phone) { this.$message.closeAll() this.$message.error('請先輸入手機號碼') return } if (!isvalidPhoneNumber(params.phone)) { this.$message.closeAll() this.$message.error('手機號格式不正確') return } this.loading = true this.$request.httpRequest({ method: 'post', url: this.API.SendSms, returnFullData: true, noLoading: true, hideErrorMsg: true, params: params, success: (data) => { this.loading = false this.$message.closeAll() this.$message.success('驗證碼發送成功,請留意手機短信') const sendTimer = setInterval(() => { this.isOvertime = true this.word = `${this.time}s後從新獲取` this.time-- if (this.time <= 0) { this.isOvertime = false this.time = 60 clearInterval(sendTimer) this.word = '獲取驗證碼' } }, 1000) }, error: (e) => { this.loading = false const errorMsg = e.hasOwnProperty('resultMessage') ? e.resultMessage : '獲取驗證碼失敗' this.$message({ message: errorMsg, type: 'error', customClass: 'errorloginwidth', duration: 3000 }) } }) } 複製代碼