一、导航守卫
导航守卫:导航是正在发生变化的路由;从当前的组件离开准备去往下一个组件;
什么需要导航守卫?
真实项目中,我们需要根据用户权限、登录状态来决定用户可以看到的页面;但是路由就在浏览器地址栏里面,如果不加以拦截,用户通过在地址栏中输入,就可以看到他本不该看到的页面;所以我们使用导航守卫拦截它;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<router-link to="/articles/1/x?name=mabin&age=18">文章1</router-link>
<button @click="toArticle">去文章1</button>
<router-view></router-view>
</div>
<template id="listTpl">
<div>
<div>LIST <button @click="goBack">返回</button></div>
<div>
<router-link to="/list/view">查看</router-link>
<router-link to="/list/modify">修改</router-link>
</div>
<router-view></router-view>
</div>
</template>
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<script>
let home = {
template: `<div>HOME <button @click="toList">去列表</button></div>`,
methods: {
toList() {
// 用方法切路由,push 是去指定的路由
this.$router.push('/list')
}
}
};
let list = {
template: `#listTpl`,
methods: {
goBack() {
// 返回上一页(上一个组件)
this.$router.go(-1);
}
}
};
let view = {
template: `<div>查看</div>`
};
let modify = {
template: `<div>修改</div>`
};
let articles = {
template: `<div>第{{$route.params.id}}篇文章</div>`,
created() {
console.log(this.$route.params);
console.log(this.$route.query);
}
};
// /articles/1/x
let routes = [
{
name: 'articles',
path: '/articles/:id/:text',
component: articles
},
{
path: '/',
component: home
},
{
path: '/home',
component: home
},
{
path: '/list',
component: list,
children: [
{
path: 'view',
component: view
},
{
path: 'modify',
component: modify
}
]
}
];
let router = new VueRouter({
routes
});
// 全局前置导航守卫: 对所有的路由都生效;
router.beforeEach((to, from, next) => {
// to 路由对象,包含将要去往的路由的信息
// from 路由对象,包含了正要离开的路由的信息
// next 控制权函数,如果通过验证执行 next() 交出控制权;
console.log(to);
console.log(from);
// console.log(next);
// 在这个函数中就可以做拦截,例如从 cookie 中获取登录状态,如果登录了,执行 next() 交出控制权;
// next() 没有任何问题,交出控制权
// next(false) 中断当前导航,如果 url 发生变化,会回退到当前页面的路由
// next(路由或路由对象) 直接重定向到指定的路由
// 无论哪种情况都要执行对应的 next,如果不执行就会处于挂起状态;
let isLogin = document.cookie.includes('isLogin=true');
// debugger;
if (to.fullPath === '/list/view') {
// /list/view 假设现在不需要验证权限,所以访问 /list/view 直接放行
next()
} else {
if (isLogin) {
next()
} else {
// next('/list/view'); // 重定向到 view
next(false); // 中断导航,不能从当前页离开
}
}
// next();
});
let vm = new Vue({
el: '#app',
router,
methods: {
toArticle() {
// 点击 router-link 和执行下面的方法效果一样
this.$router.push({
name: 'articles',
params: {id: 1, text: 'x'},
query: {
name: 'mabin',
age: 18
}
})
}
}
})
</script>
</body>
</html>
二、路由独享守卫
<body>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<router-view></router-view>
</div>
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<script>
let home = {
template: `<div>HOME</div>`
};
let about = {
template: `<div>About</div>`
};
// 配置路由映射表
let routes = [
{
path: '/',
component: home
},
{
path: '/home',
component: home
},
{
path: '/about',
component: about,
beforeEnter(to, from, next) {
// 路由独享守卫:配置在路由映射表中
console.log(to);
console.log(from);
console.log(next);
// 在这个钩子中做校验,如果校验通过执行 next() 否则 next(false) 或者 重定向到某一个路由;
next(); // 没问题放行
// next(false); // 中断导航
// next('/home'); // 重定向到某个路由
// 无论执行哪一种 next,都要执行一个;
}
}
];
// 创建 VueRouter 实例
let router = new VueRouter({
routes
});
let vm = new Vue({
el: '#app',
router
})
</script>
</body>
三、组件内守卫
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about/12">关于12</router-link>
<router-link to="/about/13">关于13</router-link>
<router-view></router-view>
</div>
<script src="vue.js"></script>
<script src="vue-router.js"></script>
<script>
let home = {
template: `<div>HOME</div>`
};
let about = {
template: `<div>About</div>`,
beforeRouteEnter(to, from, next) {
// 在渲染路由对应的该组件前被调用,
// 不!能!访问 this,因为此时 vue 实例尚未创建
// to/from/next 和全局守卫一样的意义
// next();
// next(false);
// next('/home')
next();
},
beforeRouteUpdate(to, from, next) {
// 当前路由发生改变,但是组件被复用(没销毁)时被调用;适用于动态路由的参数发生变化时
// 要去往的路由参数 to.params
// 正要离开的路由的参数 from.params
console.log(to.params.id);
console.log(from.params.id);
next()
},
beforeRouteLeave(to, from, next) {
// 导航要离开当前组件对应的路由时调用,从当前页去往其他页面的时候调用;可以用来做离开时提示用户信息没保存;
let doLeave = confirm('信息尚未保存,确定要离开吗?');
if (doLeave) {
next()
}
}
};
// 配置路由映射表
let routes = [
{
path: '/',
component: home
},
{
path: '/home',
component: home
},
{
path: '/about/:id',
component: about,
}
];
// 创建 VueRouter 实例
let router = new VueRouter({
routes
});
let vm = new Vue({
el: '#app',
router
})
</script>
</body>
</html>