這篇主要處理在登錄頁面點擊按鈕,給后台api發請求的操作
涉及到的改動有以下部分:
1、utils目錄下新建myrequest.js文件 【這里主要模仿框架的request.js】封裝屬於自己的返回代碼和提示信息
utils目錄下此文件主要功能就是創建axion實例、初始化請求的base_url,另外就是設置request在發送請求前的一些操作和response收到請求后的一些操作。比如發請求前添加headers,收到請求后根據code值進行頁面跳轉或者提示
2、在api目錄下新建myuser.js文件【這里主要模仿框架的user.js】,這個api文件主要負責發送請求並返回請求的內容
3、在store文件夾--modules文件夾下還有個user.js 這里面定義了button點擊后form表單提交處理的邏輯
現在開始正題
a、因為要實現點擊登錄按鈕,調用api,所以先看mylogin的index頁面里,button綁定的事件:
<el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登 錄</el-button>
可以看到綁定了handleLogin方法,此方法分兩部分,一部分為驗證表單輸入的正確性和必要性,另外一部分就是提交表單數據到某個地方了,可以看以下代碼
this.$store .dispatch('user/Mylogin', this.myLoginForm) .then(() => { this.$router.push({ path: this.redirect || '/' }) // 路由傳值,用於導航到下一個頁面 登錄成功之后重定向this.redirect或者'/'首頁 this.loading = false }) .catch(err => { this.$message.error(err) // 登錄失敗提示錯誤 this.loading = false })
其中this.$store.dispatch('user/Mylogin', this.myLoginForm)就是將表單數據提交到了store--modules--user.js文件里的 Mylogin方法,原框架寫的是login方法提交成功后,就執行路由方法跳轉到下一頁面
b、下來接着看store--modules--user.js文件里的 Mylogin方法
參考原來的login方法,寫了自己的Mylogin方法,這個頁面我們引用了自己寫的user請求里的api_login以及api_logout,然后在Mylogin里調用了api_login並將表單的參數傳遞了進去
// 自己頁面的 login方法 Mylogin({ commit }, userInfo) { const { username, password } = userInfo // es6的寫法,可以用常量直接匹配等號后面的對象
// Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理 return new Promise((resolve, reject) => { api_login({ username: username.trim(), password: password }).then(response => { const res = response // 將請求結果賦值給常量 commit('SET_TOKEN', res.Result.token) // 設置store 狀態管理里面的token commit('SET_NAME', res.Result.name) commit('SET_AVATAR', 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif') setToken(res.Result.token) // 設置token到cookie resolve() // 執行成功的方法 }).catch(error => { reject(error) // 返回失敗的方法 }) }) },
以下為修改后的user.js全文件

// import { login, logout, getInfo } from '@/api/user' // 框架原來自帶user相關api接口 import { api_login, api_logout } from '@/api/myuser' // 自己的user請求接口 import { getToken, setToken, removeToken } from '@/utils/auth' import { resetRouter } from '@/router' // 獲取用戶默認狀態 const getDefaultState = () => { return { token: getToken(), name: '', avatar: '' } } const state = getDefaultState() const mutations = { // 重置用戶狀態 RESET_STATE: (state) => { Object.assign(state, getDefaultState()) }, // 用戶token SET_TOKEN: (state, token) => { state.token = token }, // 用戶姓名 SET_NAME: (state, name) => { state.name = name }, // 用戶圖像 SET_AVATAR: (state, avatar) => { state.avatar = avatar } } const actions = { // user login // login({ commit }, userInfo) { // const { username, password } = userInfo // return new Promise((resolve, reject) => { // login({ username: username.trim(), password: password }).then(response => { // const { data } = response // commit('SET_TOKEN', data.token) // setToken(data.token) // resolve() // }).catch(error => { // reject(error) // }) // }) // }, // 自己頁面的 login方法 Mylogin({ commit }, userInfo) { const { username, password } = userInfo // Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理 return new Promise((resolve, reject) => { api_login({ username: username.trim(), password: password }).then(response => { const res = response // 將請求結果賦值給常量 commit('SET_TOKEN', res.Result.token) // 設置store 狀態管理里面的token commit('SET_NAME', res.Result.name) commit('SET_AVATAR', 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif') setToken(res.Result.token) // 設置token到cookie resolve() // 執行成功的方法 }).catch(error => { reject(error) // 返回失敗的方法 }) }) }, // user logout logout({ commit, state }) { return new Promise((resolve, reject) => { api_logout(state.token).then(() => { removeToken() // must remove token first resetRouter() commit('RESET_STATE') resolve() }).catch(error => { reject(error) }) }) }, // remove token resetToken({ commit }) { return new Promise(resolve => { removeToken() // must remove token first commit('RESET_STATE') resolve() }) } } export default { namespaced: true, state, mutations, actions }
c、因為上面調用了api_login,所以可以看看原來api目錄下的user.js 來寫我們自己的myuser.js里api_login方法
代碼里是我自己api請求的相關參數及命名,方法中主要給請求的url、類型、及data數據賦值 ,具體代碼如下:

import request from '@/utils/myrequest' export function api_login(data) { return request({ url: 'xxxxxxxxx/Login', method: 'post', data: { login_name: data.username, pwd: data.password, code: '' } }) } export function api_logout(data) { return request({ url: 'https://xxxxxxxxxx/LoginOut', method: 'post', data: { token: data.token } }) }
d、api_login中引用了utils文件夾中的request.js,所以我們也照貓畫虎創建一個自己的myrequest.js

// 導入axios請求封裝類 import axios from 'axios' // 導入element的message及messagebox方法 import { MessageBox, Message } from 'element-ui' // 導入自定義的store 狀態管理 import store from '@/store' // 導入自定義工具類auth的獲取token方法 import { getToken } from '@/utils/auth' // 創建實例 create an axios instance const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url // withCredentials: true, // send cookies when cross-domain requests timeout: 5000 // 設置請求超時時間 }) // request請求攔截器 service.interceptors.request.use( config => { // 在request發送前做一些操作 if (store.getters.token) { // 在這里添加可以使每個reqeust請求頭都帶上x-token這個屬性,可根據實際項目情況修改 config.headers['X-Token'] = getToken() } return config }, error => { // do something with request error console.log(error) // for debug return Promise.reject(error) // 給Promise.reject()的失敗方法傳遞參數 } ) // Response的攔截器 service.interceptors.response.use( /** * If you want to get http information such as headers or status * Please return response => response */ /** * Determine the request status by custom code * Here is just an example * You can also judge the status by HTTP Status Code */ response => { const res = response.data // console.log(typeof (res.Code)) // 如果api請求返回值code不是10000,說明請求出錯了. 請根據實際項目情況修改 if (res.Code !== 10000) { // 側邊欄彈框提示消息 Message({ message: res.message || '收到請求后比較code值出現異常,請檢查大小寫', // 消息內容 type: 'error', // success,error,info,warning 彈框類型 duration: 5 * 1000 // 顯示時間 }) // 10004: Token expired; if (res.Code === 10004) { // 彈出登陸框重新登錄或取消 MessageBox.confirm('Token已失效,可選擇重新登錄或取消', '提示:', { confirmButtonText: '重新登陸', cancelButtonText: '取消', type: 'warning' }).then(() => { store.dispatch('user/resetToken') // 用戶點擊重新登陸時 跳轉到store下的user文件執行resetToken方法 .then(() => { location.reload() // 執行成功后重新載入當前文檔 }) }) } return Promise.reject(new Error(res.message || 'Error')) } else { return res // 將成功的消息返回 } }, error => { console.log('err' + error) // for debug // 側邊欄彈框提示消息 Message({ message: error.message, // 消息內容 type: 'error', // success,error,info,warning duration: 5 * 1000 // 彈框顯示時間 }) return Promise.reject(error) } ) export default service
做完以上步驟整個調用就算是改完了。跑起來看看效果:
頁面提示Error,控制台中看到第一個錯誤提示是:[Vue warn]: data functions should return an object: 后來查詢了好久發現框架中res.code是小寫的,而我自己的api返回json中Code第一個字母是大寫的
解決了這個問題之后,點擊登陸頁面沒再出現Error的錯誤。
但是又出現新的錯誤: