包括配置环境变量封装 axios、接口请求模块、vuex 登录请求动作、保存服务端的 token、登录鉴权
一、配置环境变量及封装 axios 模块
在跟目录下创建.env.development .env.production 2 个文件
1 2 3 4 5 6 7
| ENV = "development"; VUE_APP_BASE_API = "/api";
ENV = "production"; VUE_APP_BASE_APIU = "/prod-api";
|
axios 的封装 utils 下创建 request.js
1 2 3 4 5 6 7
| import axios from "axios"; const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 5000, });
export default service;
|
二、封装登录请求动作
根目录下的 src 下创建 api 文件夹,touch sys.js
1 2 3 4 5 6 7 8
| import request from "@/utils/request"; export const login = (data) => { return request({ url: "/sys/login", method: "PSOT", data, }); };
|
将登录请求的动作封装到 vuex 的 action 中,在store
文件夹下创建 modules 文件夹,在 modules 下touch user.js
模块(此模块用于处理所有和用户相关的内容)
安装 md5 插件,加密登录密码 yarn add md5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import { login } from '@/api/sys' import md5 from 'md5' export default { namespaced: true, state: () => ({}), mutations: {}, actions: { login(context, userInfo) { const { username, password } = userInfo return new Promise((resolve, reject) => { login({ username, password: md5(password) }) .then(data => { resolve() }) .catch(err => { reject(err) }) }) } } }
import { createStore } from 'vuex' import user from './modules/user.js' export default createStore({ modules:{ user } })
|
在登录页,触发定义的 action,此时存在一个问题就是,我们当前请求的接口不存在,需要使用 devServer 代理
1 2 3 4 5 6 7 8 9 10 11 12
| module.exports = { devService: { proxy: { "/api": { target: "https://api.xxx.com", changeOrigin: true, }, }, }, };
|
重启项目,再次点击登录,就可以跳转到首页了。
三、本地缓存的处理
登录成功之后,前端会拿到后端返回的 token,我们需要将 token 进行缓存
缓存的 2 种方式:
1、本地缓存:localStorage
2、全局状态管理: vuex
localStorage 可以方便实现自动登录功能
保存在 vuex 中是为了后面在其他位置进行使用
(一)、localStorage
在 utils 文件夹下,新建 storage..js
1、封装 4 个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
export const setItem = (key, value) => { if (typeof value === "object") { value = JSON.stringify(value); } window.localStorage.setItem(key, value); };
export const getItem = (key) => { const data = window.localStorage.getItem(key); try { return JSON.parse(data); } catch (err) { return data; } };
export const removeItem = (key) => { window.localStorage.removeItem(key); };
export const removeAllItem = (key) => { window.localStorage.clear(); };
|
(二)、vuex 处理 token
在 store 的 user.js 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import { login } from '@/api/sys' import md5 from 'md5' import { setItem, getItem } from '@/utils/storage'
import { TOKEN } from '@/constant' export default { namespaced: true, state: () => ({ token: getItem(TOKEN) || '' }), mutations: { setToken(state, token) { state.token = token setItem(TOKEN, token) } }, actions: { login(context, userInfo) { ... .then(data => { this.commit('user/setToken', data.data.data.token) resolve() }) ... }) } } }
|
四、响应数据的统一处理
上面这一行代码this.commit('user/setToken', data.data.data.token)
,需要使用 data.data.data.token,书写方式不美观。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| import axios from 'axios' import { ElMessage } from 'element-plus'
...
service.interceptors.response.use( response => { const { success, message, data } = response.data if (success) { return data } else { ElMessage.error(message) return Promise.reject(new Error(message)) } }, error => { ElMessage.error(error.message) return Promise.reject(error) } )
export default service
|
上面的代码简写为:
1
| this.commit("user/setToken", data.token);
|