路由导航守卫:导航守卫就是在路由跳转前后的一些钩子函数
路由守卫分为三种:全局导航守卫,路由守卫,组件内导航守卫。路由跳转本身是一个比较复杂的过程,但是可以通过导航守卫把这个过程进行细化,可以在每个细化的过程(钩子函数)中进行相应的操作。
路由拦截:在路由跳转到指定的路有前,可以手动让其跳转到其他的路由界面,并且也可以让跳转停止掉。
1 全局守卫:
全局前置守卫:beforeEach 会多次触发,
全局解析守卫:beforeResolve 解析守卫
全局后置守卫:afterEach 把组件实例对象传入到组件beforeRouteEnter守卫的next回调中
2.路由守卫:
beforeEnter 路由内的独享守卫
3.组件内的守卫:
beforeRouteEnter 进入组件之前触发,只在进入组件时触发一次
beforeRouterUpdate 组件更新之前触发(动态参数变化查询字符串变化)进入组件后参数变化可多次触发
beforeRouterLeave 离开路由组件之前触发 只在离开组件时触发一次
1.先在失活的组件里面执行组件离开的守卫(beforeRouterLeave)
2.调用全局前置守卫(beforeEach)
3.在重复使用组件执行beforeRouteUpdate
4.在去执行路由独享守卫beforeEnter
5.在激活的组件里面执行beforeRouteEnter守卫
6.执行全局的解析守卫 beforeResolve
7.执行全局的后置守卫 afterEach
8.再去执行beforeRouteEnter里面的回调函数next(组件实例对象)
// 全局导航守卫在router/index.js 下面添加
//全局的前置守卫:可以进行登陆界面是否要显示,判断是否需要进行登录判断
router.beforeEach((to,from,next)=>{
// to:目标路由的配置对象(到哪去)
// from:是跳转前的路由对象(从哪来)
// next//把当前跳转操作交给下一个路由守卫,如果不添加next,这个时候跳转就会停止掉
console.log("1 beforeEach,只要路由发生变化都会触发的钩子函数,或者每一次路由进入也会触发");
// to.matched 找到目标路由下所有的不管是一级路由还是二级路由
// record.meta.requireLogin 找到一个路由匹配对象的 requireLogin:true
var token = localStorage.getItem("ll")//获取登录成功的token
if (to.matched.some(record=>{return record.meta.requireLogin})) {
// 条件成立说明需要进行登陆判断
if (token) {
// 存在token则跳转继续,显示目标路由
next()
}else{
// 没登陆直接进入登陆界面
next("/login")
}
}else{ //else说明不需要登录判断,直接跳转目标路由
next()//把当前跳转操作交给下一个路由守卫,如果不添加next(),这个时候跳转就会停止掉.next(false)会停止路由的跳转
}
})
router.beforeResolve((to,from,next)=>{
console.log(to,from,2);
next()
})
全局后置守卫执行结束会执行组件前置守卫中的next函数
router.afterEach((to,from,next)=>{
console.log(to,from,3);
})
const routes = [
{
path: '/demo/:id',
name: 'Demo',
component: () => { //只走一次,留下缓存,后面使用缓存
console.log("解析组件demo的过程");
return import('../views/Demo.vue')},
meta:{requireLogin:true},//添加一个元数据,自定义属性,可以在守卫函数通过to或者from取到元数据,然后可以通过requireLogin进行判断该路由是否需要进行登陆判断
// 第二种类型:路由独享守卫
beforeEnter: (to, from, next) => {
console.log('在进入到一个路由之前,专门用来守卫当前路由的。如果是同一个路由下的两个子路由在进行跳转的时候不会触发,必须重新进入才会触发');
next()
}
},
]
// 第三种导航守卫,写在一个组件的内部,组件内的守卫
beforeRouteEnter: (to, from, next) => {
// console.log(this);//undefined 组件实例不存在,没有this
console.log("进入到当前路由组件之前调用");
next(vm=>{
//vm创建好的组件实例,即this对象
vm.http.get("/books.json").then(res=>{
vm.books = res.data.data
console.log(vm.books,"在全局后置守卫执行之后把组件实例传入到组件守卫的beforeRouteEnter的next函数里面");
})
})
},
beforeRouteUpdate (to, from, next) {
console.log("当前路由组件更新的时候调用,当动态路由参数发生变化的时候触发,例如/demo/1和/demo/2,当查询字符串发生变化的时候也会触发");
this.b = this.books.filter((b,j)=>{
return b.id == to.params.id
})
next()
},
beforeRouteLeave (to, from, next) {
console.log("当离开当前路由组件之前调用,一般是在离开之前是否还有其它操作没有");
var answer = window.confirm("Do you want leave this page,has some unsave changes?")
if (answer) {
next()
}else{
next(false)//停止导航切换.0.0
}
}