目录
1.2 全局路由守卫 - beforeEach 和 afterEach(Vue Router3)
1.3 独享路由守卫 - beforeEnter(Vue Router3)
一、路由守卫
1.1 简介
作用:对路由进行权限控制
分类:全局守卫、独享守卫、组件内守卫
官方文档:
1.2 全局路由守卫 - beforeEach 和 afterEach(Vue Router3)
const router = new VueRouter({ ... })
// 全局前置路由守卫 - 初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to, from, next) => {
// ...
})
// 全局后置路由守卫 - 初始化的时候被调用、每次路由切换之前被调用
router.afterEach((to, from, next) => {
// ...
})
/*
to: 即将要进入的目标 路由对象
from: 当前导航正要离开的路由
*/
1.2.1 案例练习
主要修改的是src/router/index.js
- 为每个路由配置name属性和meta属性
- const router 等于所创建的路由,并导出
- 为news路由和message路由meta属性内添加上isAuth:true用于判断是否需要鉴权
- 在控制台Local Storage添加键值对(key-value):user-zhang3
src/router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
// 引入组件
import About from "../pages/About.vue";
import Home from "../pages/Home.vue";
import Message from "../pages/Message.vue";
import News from "../pages/News.vue";
import Detail from "../pages/Detail.vue";
const router = new VueRouter({
routes: [
{
name: "about",
path: "/about",
component: About,
meta: { title: "关于" },
},
{
name: "home",
path: "/home",
component: Home,
meta: { title: "主页" },
// 通过children配置二级路由
children: [
{
name: "message",
path: "message",
component: Message,
meta: { isAuth: true, title: "消息" },
children: [
{
name: "detail1",
path: "detail/:id/:title", // 使用占位符声明接收params参数
component: Detail,
// props配置:props为布尔值,布尔值为true,则把路由收到的所有params参数通过props传给Detail组件
props: true,
},
],
},
{
name: "news",
path: "news",
component: News,
meta: { isAuth: true, title: "新闻" },
children: [
{
name: "detail2",
path: "detail",
component: Detail,
meta: { title: "详情" },
// props配置:props值为函数,该函数返回的对象中每一组key-value都会通过props传给Detail组件
props($route) {
return { id: $route.query.id, title: $route.query.title };
},
},
],
},
],
},
],
});
export default router;
全局前置路由守卫部分:
// 全局前置路由守卫 - 初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to, from, next) => {
console.log("前置路由守卫", to, from);
// 判断是否需要鉴权
if (to.meta.isAuth) {
// 权限控制的具体规则
if (localStorage.getItem("user") === "admin") {
document.title = to.meta.title || "测试路由守卫"; // 修改网页title
next(); // 放行
} else {
alert("不具备权限访问");
}
} else {
next(); // 放行
}
});
全局后置路由守卫部分:
// 全局后置路由守卫 - 初始化的时候被调用、每次路由切换之前被调用
router.afterEach((to, from) => {
console.log("后置路由守卫", to, from);
document.title = to.meta.title || "测试路由守卫";
});
/*
全局后置路由守卫
1. 可用于分析、更改页面标题、声明页面等辅助功能以及许多其他事情
2. 不会接受 next 函数也不会改变导航本身
*/
当Local Storage键值对不符合权限控制的具体规则时,会出现下方图片的情况
当Local Storage键值对符合权限控制的具体规则时,即键值对为user-admin,便可进入news路由和message路由
1.3 独享路由守卫 - beforeEnter(Vue Router3)
- 可以直接在路由配置上定义 beforeEnter 守卫
- beforeEnter 守卫 只在进入路由时触发,不会在 params、query 或 hash 改变时触发
const router = new VueRouter({
routes: [
{
path: '/路径',
component: 组件,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
1.3.1 案例练习
- 为news路由配置 beforeEnter 守卫
- 在控制台Local Storage添加键值对(key-value):user-zhang3
- 如果先前有写全局前置路由,需先注销
....
{
name: "news",
path: "news",
component: News,
meta: { isAuth: true, title: "新闻" },
// 为news路由配置独立路由守卫
beforeEnter: (to, from, next) => {
console.log("独立路由守卫", to, from);
// 判断是否需要鉴权
if (to.meta.isAuth) {
if (localStorage.getItem("user") === "admin") {
document.title = to.meta.title || "测试路由守卫";
next();
} else {
alert("不具备权限访问");
}
} else {
next();
}
},
children: [
{
...
},
},
],
},
由下图可看出,当Local Storage键值对不符合权限控制的具体规则时,不能进入news路由,但依然可以进入message路由
由下图可看出,当Local Storage键值对符合权限控制的具体规则时,才能进入news路由
1.4 组件内路由守卫 - (Vue Router3)
- beforeRouteEnter
- beforeRouteUpdate (2.2 新增)
- beforeRouteLeave
<script>
export default {
name: "自定义组件命名",
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
};
</script>
1.4.1 案例练习
- 在about路由组件配置上定义 beforeEnter 守卫 和 beforeRouteLeave守卫
- 在控制台Local Storage添加键值对(key-value):user-zhang3
src/router/index.js 下为 about路由meta属性内添加上isAuth:true用于判断是否需要鉴权
const router = new VueRouter({
routes: [
{
name: "about",
path: "/about",
component: About,
meta: { isAuth: true, title: "关于" },
},
.....
],
});
About.vue路由组件 配置上定义 beforeEnter 守卫 和 beforeRouteLeave守卫
<template>
<div>
<h1>About相关内容</h1>
</div>
</template>
<script>
export default {
name: "About",
// 组件内beforeRouteEnter路由守卫,通过路由规则,进入组件时被调用
beforeRouteEnter(to, from, next) {
console.log("组件内beforeRouteEnter路由守卫", to, from);
// 判断是否需要鉴权
if (to.meta.isAuth) {
if (localStorage.getItem("user") === "admin") {
document.title = to.meta.title || "测试路由守卫";
next();
} else {
alert("不具备权限访问");
}
} else {
next();
}
},
// 组件内beforeRouteLeave路由守卫,通过路由规则,离开组件时被调用
beforeRouteLeave(to, from, next) {
console.log("组件内beforeRouteLeave路由守卫", to, from);
next();
},
};
</script>
由下图可看出,当Local Storage键值对不符合权限控制的具体规则时,不能进入about路由
由下图可看出,当Local Storage键值对符合权限控制的具体规则时,才能进入about路由,且只有点击并切换了其他路由才能触发beforeRouteLeave路由守卫被调用
二、history模式 与 hash模式
1. 对于一个url来说,什么是hash值? —— #及其后面的内容就是hash值
2. hash值不会包含在HTTP请求中,即hash值不会带给服务器
3. hash模式:
(1)地址中永远带着#号,不美观
(2)若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
(3)兼容性好
4. history模式:
(1)地址干净,美观
(2)兼容性和hash模式相比略差
(3)应用部署上线时需要后端人员支持,解决刷新页面服务器404的问题