这篇主要处理在登录页面点击按钮,给后台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的错误。
但是又出现新的错误: