【vue3】:前端登录功能解决方案
усилの博客 2022/6/26 方案vue3element-plusJWT
# # 后台登录功能解决方案
# # 配置生产环境和开发环境
// .env.development
# 标志
ENV = 'development'
# base api
VUE_APP_BASE_API = '/api'
1
2
3
4
5
6
2
3
4
5
6
// .env.production
# 标志
ENV = 'production'
# base api
VUE_APP_BASE_API = '/prod-api'
1
2
3
4
5
6
2
3
4
5
6
# # 配置接口代理
// vue.config.js
module.exports = {
devServer: {
proxy: {
"/api": {
target: "后台地址",
changeOrigin: true, // 是否跨域
},
},
},
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# # 封装 axios 模块
// require.js
import axios from "axios";
import { ElMessage } from "element-plus";
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000,
});
// 请求接口拦截
service.interceptors.request.use((config) => {
// 统一添加请求参数
config.headers.code = "参数值";
return config;
});
// 响应拦截器
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
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
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
# # 基于 localstorage 封装保存服务端返回的 token
// 设置值
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.renoveItem(key);
};
// 删除所有数据
export const removeAllItem = (key) => {
window.localStorage.clear();
};
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
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
# # 封装 接口请求 模块
// sys.js
import request from "@/utils/require";
// 登录 API
export const login = (data) => {
return request({
url: "/sys/login",
method: "POST",
data,
});
};
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# # 封装登录请求动作
单独将有关用户部分的请求封装到 vuex
中的user
模块中
import { login } from "@/api/sys";
import md5 from "md5";
import { setItem, getItem } from "@/utils/storage";
import router from "@/router";
export default {
namespaced: true, // 该模块为单独的模块
state: () => ({
token: getItem(TOKEN) || "",
}),
mutations: {
setToken(state, token) {
state.token = token;
setItem("token", token);
},
},
actions: {
// 登录请求动作
login(context, userInfo) {
const { username, password } = userInfo;
return new Promise((resolve, reject) => {
login({
username,
password: md5(password),
})
.then((data) => {
// 登录成功 调用 setToken 将 值存放到 localstorage 及 vuex
this.commit("user/setToken", data.token);
// 跳转
router.push("/");
resolve();
})
.catch((err) => {
reject(err);
});
});
},
},
};
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
37
38
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
37
38
在 store 入口文件index.js
中注册 user 模块
import { createStore } from "vuex";
import user from "./modules/user.js";
import getters from "./getters";
export default createStore({
getters,
modules: {
user,
},
});
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# # 登录鉴权
在访问项目时,需要判断用户是否已经登录了,登录了则直接进入到主页。反则,跳转到登录到页面。
使用 vue-router
前置路由来进行登录鉴权
// permission.js
import router from "./router";
import store from "./store";
// 白名单 (无需登录,即可访问的页面)
const whiteList = ["/login"];
router.beforeEach(async (to, from, next) => {
if (store.getters.token) {
// 已登录
if (to.path === "/login") {
// 访问登录界面
next("/"); // 直接进入到主页
} else {
next(); // 正常
}
} else {
// 未登录
if (whiteList.indexOf(to.path) > -1) {
next();
} else {
next("/login");
}
}
});
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// main.js
// 导入路由鉴权
import "./permission";
1
2
3
2
3
# # 使用
<el-button type="primary" :loading="loading" @click="handleLogin"
>登录</el-button
>
<script setup>
import { useStore } from "vuex";
const handleLogin = () => {
store
.dispatch("user/login", loginForm.value)
.then(() => {
console.log("登录成功");
})
.catch((err) => {
console.log(err);
});
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16