vue-router 高阶——导航守卫
老规矩,先来解读下官方文档:vue-router提供的导航守卫主要用来通过跳转或取消的方式来守卫导航。( 简单说,导航守卫就是在路由跳转的时候的一些钩子函数,当从一个页面跳转到另一个页面时,可以在跳转前、中、后做一些事情,我们可以控制路由的跳转)。导航守卫可分为三大类:(全局守卫、路由专享守卫、组件守卫)一、全局守卫又可分为三个:(1)全局前置守卫:rout...
老规矩,先来解读下官方文档:
vue-router提供的导航守卫主要用来通过跳转或取消的方式来守卫导航。( 简单说,导航守卫就是在路由跳转的时候的一些钩子函数,当从一个页面跳转到另一个页面时,可以在跳转前、中、后做一些事情,我们可以控制路由的跳转 )。
导航守卫可分为 三大类:( 全局守卫、路由专享守卫、组件守卫)
一、全局守卫又可分为三个:
(1)全局前置守卫:(项目必用!!!)
router.beforeEach( to,from,next ) =>{ }
(2)全局解析守卫:
router.beforeResolve( to,from,next ) =>{ }
(3)全局后置守卫:
router.afterEach( to,from )=>{ }
二、路由专享守卫:
const router = new VueRouter({
routes: [
{
path: '/play',
component: Play,
beforeEnter: (to, from, next) => {}
}
]
})
三、组件中的守卫:
(1)beforeRouteEnter
(2)beforeRouteUpdate
(3)beforeRouteLeave
export default {
name:'play',
beforeRouteEnter(to,from,next){
},
beforeRouteUpdate(to,from,next){
},
beforeRouteLeave(to,from,next){
}
}
****************** 详解 ***********************************
全局前置守卫 router.beforeEach( ( to,from,next)=>{ } ):
1、常用于登录验证;
2、使用 router.beforeEach 可注册一个全局前置守卫;
3、每当一个导航被触发时,首先被调用的总是全局前置守卫 ;
4、该守卫接受三个参数:to、from、next,三个参数意思分别是:
to —— 即将要进入的目标路由对象(路由对象);
from —— 当前导航正要离开的路由(路由对象);
next —— 此方法,必须调用,如果想跳转的话,否则路由将不会跳转(function)。
router.beforeEach((to,from,next)=>{
console.log(to)
console.log(from)
console.log(next)
next()
})
上边代码,我们分别打印下这三个参数看下:
从首页(根路径)路由名字为first的页面 跳转到 路由名字 为play页面;
to :正是跳转后的目标路有对象play;
to.path 和to.fullPath的区别:
to.path - 当前的路径,始终解析为绝对路径;to.fullPath - 完整的解析URL包含查询参数和哈希。
from:是之前的路由对象 first。
next:则是一个函数,next函数决定路由是否跳转;
next( ) 参数问题:
next( false) 可传false,当用户点击浏览器后退按钮时,url地址会重置到from路由对象的地址(通俗说,就是路由不会跳转了!!!)
next( "/")或者 next({path:"/"})可以传路径,它会跳转到不同地址。例如:下边当用户访问路由名为play对应的页面时候,它会被终止,直接会被重定向到路径为 “ /news ” 的页面。
router.beforeEach((to,from,next)=>{
if(to.name == "play"){
next({path:"/news"})
}
next()
})
全局解析守卫 router.beforeResolve( ( to,from,next)=>{ } )
官方文档:2.5.0新增的一个守卫,在导航被确认之前,同时在所有组件守卫和异步路由被解析之后(加载完之后),解析守卫会被调用。。。
全局后置钩子router.afterEach( ( to,from)=>{ } )
与守卫不同的是,此钩子函数不会接受next函数,也不会改变导航本身。。。是在全局解析守卫之后被调用。。。
路由独享守卫beforeEnter : ( to,from,next)=>{ }
const router = new VueRouter({
routes: [
{
path: '/play',
component: Play,
beforeEnter: (to, from, next) => {}
}
]
})
组件内守卫beforeRouterEnter : ( to,from,next)=>{ }
export default {
name:'play',
beforeRouteEnter(to,from,next){
// 在渲染组件前调用,不能获取this,组件实例还未被挂载
next()
},
beforeRouteUpdate(to,from,next){
// 在当前路由改变,但当前组件被复用时调用,
// 比如:带有动态参数的路径,/foo/1 跳转 /foo/2 时,
// 该钩子函数被调用。(可访问组件实例this)
next()
},
beforeRouteLeave(to,from,next){
// 离开该组件对应的路由时,该钩子函数会被调用
next()
}
}
beforeRouterEnter 守卫不能够访问this,因为守卫在导航确认前被掉用,即将登场的新组件还未被创建。。。
当然如果你非要在此守卫中用到this,官方也给出了一个方法,你可以在next函数中传一个回调函数,并把实例作为参数传到回调函数中去,这样您就可以使用this了!!!!(补充下:next中的回调在组件加载完之后执行,最后我整理了一张完整的执行顺序图)
export default {
name:'play',
beforeRouteEnter(to,from,next){
next((_this)=>{
// 通过 _this来访问实例
})
}
}
《《《官方提醒》》》
beforeRouterEnter是支持给next函数传递回调的唯一守卫;
对于beforeRouterUpdate守卫 和 beforeRouterLeave守卫来说,this已经可以用了,所以不支持传递回调,也没意义!!!
组件内守卫beforeRouterUpdate : ( to,from,next)=>{ }
下边例子中,路由页 "/news/:xxx" 会被复用,beforeRouterUpdate 守卫会被触发!!!
<template>
<div>
<div v-for="item in my_data" :key="item.id">
<router-link :to="'/news/' +item.id">{{item.name}}</router-link>
</div>
<h1>{{this.$route.params.id}}</h1>
</div>
</template>
<script>
export default {
name: "news",
data() {
return {
my_data: [
{ name: "java", id: "1" },
{ name: "python", id: "2" },
{ name: "javascript", id: "3" }
]
};
},
beforeRoutEnter(to,from,next){
console.log('news中组件内部钩子函数——beforeRouteUpdate')
next()
},
beforeRouteUpdate(to,from,next){
console.log('news中组件内部钩子函数——beforeRouteUpdate')
next()
},
beforeRouteLeave(to,from,next){
console.log('组件内部钩子函数——beforeRouteLeave)
next()
},
};
</script>
const router = new VueRouter({
routes:[
{
path:'/news/:id',
component:News,
beforeEnter:(to,from,next)=>{
console.log('news路由中的 路由独享钩子函数——beforeEnter')
next()
}
}
]
})
router.beforeEach((to,from,next)=>{
console.log('全局守卫——beforeEach')
next()
})
router.beforeResolve((to,from,next)=>{
console.log('全局守卫——beforeResolve')
next()
})
router.afterEach((to,from)=>{
console.log('全局守卫——afterEach')
})
上边代码有几个注意点:
1、从一个普通组件,切换到一个可复用的组件,先来看下执行顺序:
2、当切换可复用的页面时,也就是从 "/news/:1" ——> "/news/:2" ——> "/news/:3" 时,执行顺序:(路由独享守卫和组件内钩子beforeRouteEnter 不再执行!)
组件内守卫 beforeRouterLeave: ( to,from,next)=>{ }
此守卫是在从一个导航切换到另一个导航之后,才执行的。。。通常在此守卫可以做一些禁止用户离开的操作,比如:还未保存的草稿;或者在用户离开此导航时清除setInterval计时器,防止离开之后,计时器还在被调用等等。
router.beforeEach((to,from,next)=>{
if("用户草稿保存了"){
next() //允许跳转
}else{
next(false) //否则禁止跳转
}
})
总结:
7个守卫以及生命周期函数执行顺序:
更多推荐
所有评论(0)