Vue路由守卫与登陆权限控制

Vue 路由守卫

路由守卫,也可以是路由拦截,我们可以通过路由拦截,来判断用户是否登录,该页面用户是否有权限浏览,需要结合 meta 来实现
Vue 中路由守卫一共有三种,一个全局路由守卫,一个是组件内路由守卫,一个是 router 独享守卫

全局路由守卫

所谓全局守卫就是所有页面的路由拦截。它有两个钩子 全局前置守卫beforeEach, 全局后置守卫afterEach

全局前置守卫,就是 用户进入页面时路由拦截,进行一些处理的钩子。通常做一些页面权限控制或 title 命名之类的操作。

全局后置守卫,就是 页面成功访问的回调钩子

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
39
40
41
42
43
44
45
46
47
48
49
50
51
import Vue from "vue";
import VueRouter from "vue-router";

// Vue中插件必须use注册
Vue.use(VueRouter);

// 路由配置项,此处是路由级钩子的定义
const routes = [
{
path: "/",
component: resolve => require(["./index.vue"], resolve),
keepAlive: true
},
{
path: "/user/:userName",
keepAlive: true,
beforeEnter(to, from, next) {
console.log("router beforeEnter");
next();
},
component: resolve => require(["./user.vue"], resolve)
}
];

// 实例化路由对象
const router = new VueRouter({
routes
});

// 全局钩子
router.beforeEach((to, from, next) => {
// to: Route: 即将要进入的目标 路由对象
// from: Route: 当前导航正要离开的路由
// next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
console.log("global beforeEach");
next();
});

router.beforeResolve((to, from, next) => {
console.log("global beforeResolve");
next();
});

router.afterEach((to, from, next) => {
console.log("global afterEach");
});

// 实例化Vue对象并挂载
new Vue({
router
}).$mount("#app");

组件独享守卫

组件独享守卫是加载组件时定义的一些钩子,有beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

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
<template>
<div>
<h1>{{ msg }}</h1>
<p>我是:{{userName}}</p>
</div>
</template>

<script>
export default {
name: 'user',
data () {
return {
msg: '这里是 User Page.',
userName: 'yuwangi'
};
},
methods: {},
mounted () {
var me = this;
me.userName = me.$route.params.userName;
console.log('user mounted.');
},
beforeRouteEnter (to, from, next) {//组件激活
console.log('component beforeRouteEnter');
next();
},
beforeRouteUpdate (to, from, next) {//在当前路由改变,但是该组件被复用时调用
console.log('component beforeRouteUpdate');
next();
},
beforeRouteLeave(to,from,next){// 导航离开该组件的对应路由时调用
console.log('component beforeRouteLeave');
next();
}
};
</script>

登陆权限控制

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import Vue from "vue";
import Element from "element-ui";
import "./assets/eletheme/index.css";
import router from "./router/index";
import store from "./store/index";
import App from "./Index.vue";
import NProgress from "vue-nprogress"; //加载进度条

// import * as filters from './filters';
import * as directives from "./directive";

Vue.use(Element, { size: "small" });
Vue.use(NProgress, {});

const nprogress = new NProgress({ parent: ".app-nprogress" });

// // 全局过滤器
// Object.keys(filters).forEach(key => {
// Vue.filter(key, filters[key]);
// });

// 全局指令
Object.keys(directives).forEach(key => {
Vue.directive(key, directives[key]);
});

// 路由守卫
router.beforeEach((to, from, next) => {
// 时间统计
if (window._Timer) {
window._Timer[to.path] = window._Timer.now();
}
// 登录或者未登录跳转
const randerPath = isLogin => {
const firstPath = to.path.split("/")[1];
console.log("> isLogin", isLogin);
// 未登录操作
if (!isLogin) {
if (firstPath !== "login") {
// 根目录过来的不添加参数
if (to.fullPath === "/") {
next({
path: "/login"
});
} else {
next({
path: "/login"
// query: { redirect: to.fullPath }
});
}
} else {
next();
}
} else {
if (firstPath === "login") {
next("/");
} else {
next();
}
}
};
randerPath(window.serverData.isLogin);
});

router.afterEach(to => {
if (window._Timer && !window._Timer.inited) {
const now = parseInt(window._Timer.now() - window._Timer.start, 10);
// window.console.log('topath:', to.path);
// window.console.timeEnd('firstRouter');
window._Timer.tjTrack("timing", "router", "firstRouter", now);
window._Timer.inited = true;
}
});

// 挂载vue实例
const app = new Vue({
router,
store,
nprogress,
...App
});

app.$mount("#App");