效果
功能
- 使用Vuex 控制登录
- 鉴权控制页码访问
- 重定向后返回
views
跳转到路由组件 Home: News: 需要鉴权 User: 需要鉴权 Login: 登录页 Loading: 鉴权等待页
解决如何登录
使用loginUser
module 的状态
loginUser:有登录,退出登录,状态位置,和当前status
import * as userApi from "@/api/user.js";
export default {
// 开启命名空间, 使用mutatio必须加上模块名
namespaced: true,
state: {
loading: false,
user: null,
},
mutations: {
setLoading(state, payload) {
state.loading = payload;
},
setUser(state, payload) {
state.user = payload;
},
},
actions: {
async login(ctx, payload) {
// ctx.commit("loginUser/setLoading", true);
// 当前模块提交commit 可以省略模块名
ctx.commit("setLoading", true);
const resp = await userApi.login(payload.loginId, payload.loginPwd);
ctx.commit("setUser", resp);
ctx.commit("setLoading", false);
return resp;
},
async whoAmI(ctx, payload) {
ctx.commit("setLoading", true);
const resp = await userApi.whoAmI();
ctx.commit("setUser", resp);
ctx.commit("setLoading", false);
},
async loginOut(ctx, payload) {
ctx.commit("setLoading", true);
await userApi.loginOut();
ctx.commit("setUser", null);
ctx.commit("setLoading", false);
},
},
getters: {
status(state) {
if (state.loading) {
return "loading";
} else if (state.user) {
return "login";
} else {
return "unLogin";
}
},
},
};
鉴权
鉴权守卫示意图
如何判断哪些页面需要鉴权
在routes 给路由信息添加meta 元信息
import Home from "../views/Home.vue";
import Login from "../views/Login.vue";
import News from "../views/News.vue";
import User from "../views/User.vue";
import Loading from "../views/Loading.vue";
export default [
{ path: "/", component: Home },
{ path: "/login", component: Login },
{ path: "/loading", component: Loading },
{
path: "/news",
component: News,
meta: {
// requireAuth===true 当前路由需要鉴权
requireAuth: true,
},
},
{
path: "/user",
component: User,
meta: {
requireAuth: true,
},
},
];
路由守卫进行鉴权
import VueRouter from "vue-router";
import routes from "./routes";
import Vue from "vue";
import store from "@/store";
Vue.use(VueRouter);
const router = new VueRouter({
routes,
mode: "history",
});
// router.beforeEach当发生路由跳转便会执行
// to : 目标路由, from : 源路由, nextTick : 路由钩子可接受一个路由对象
router.beforeEach((to, from, nextTick) => {
if (to.meta.requireAuth) {
// status:[login,unLogin,loading] 三种状态
const status = store.getters["loginUser/status"];
// 状态为loading, 跳转到鉴权等待页面, 将返回地址到添加路由查询参数
if (status === "loading") {
nextTick({
path: "/loading",
query: {
returnUrl: to.fullPath,
},
});
} else if (status === "login") {
nextTick();
} else {
alert("您还没有登录,请登录!");
nextTick({
path: "/login",
query: {
returnUrl: to.fullPath,
},
});
}
} else {
nextTick();
}
});
export default router;
鉴权等待页的监控
loading.vue
<template>
<div>
<h1>loading</h1>
</div>
</template>
<script>
export default {
created() {
// 返回一个注销监视的函数
this.unWatch = this.$store.watch(
// watch: 接受三个函数,1.为监听函数返回的值, 2. 将返回值给到函数2的形参,3. 是否立即监听
() => this.$store.getters["loginUser/status"],
(status) => {
if (status !== "loading") {
// status 变化后获取当前查询参数,否为默认/home,页面跳转, 由于会发生二查重定向添加catch
this.$router
.push(this.$route.query.returnUrl || "/home")
.catch(() => { })
}
},
{
immediate: true
}
)
},
destroyed() {
this.unWatch()
},
}
</script>
<style lang="scss" scoped></style>