VueRouter-导航守卫

本文详细介绍了VueRouter中的导航守卫,包括全局守卫、路由独享守卫和组件内的守卫。通过实际示例展示了它们在页面跳转时的执行顺序,以及与Vue实例生命周期钩子的交互。强调了在组件复用和非复用场景下,不同守卫和生命周期钩子的触发情况,最后提出了在使用导航守卫时应注意的性能问题。
摘要由CSDN通过智能技术生成

在用户浏览网页,跳转页面的时候我们都会进行一些验证,这是网站项目中很普遍的需求。

对此VueRouter为我们提供了7个钩子函数,也就是常说的导航守卫(Navigation-guards)。

而VueRouter也对这7个导航守卫分为三类:全局守卫、路由独享守卫、组件内的守卫。

下面是结合了vue实例的生命周期钩子函数和导航守卫的钩子函数进行的测试:

<div id="app">
	<router-link to="/home/homeChild" tag="button">首页</router-link>
	<router-link to="/home/homeSon" tag="button">首页1</router-link>
	<router-link to="/list" tag="button">列表页</router-link>
	<router-view></router-view>
</div>

注册组件home和list,并对home绑定了beforeCreate、create、beforeMount、mounted、beforeDestroy和destroyed声明周期函数和beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave导航守卫钩子函数

let home = {
     template: '<div>首页{{$route.params.id}}</div>',
      beforeCreate() {
          console.log('这是实例创建前执行的方法:beforeCreate');
      },
      created() {
          console.log('这是实例创建后执行的方法:created');
      },
      beforeMount(){
          console.log('这是挂载前执行的方法:beforeMount');
      },
      mounted(){
          console.log('这是挂载后执行的方法:mounted');
      },
      beforeRouteEnter(to, from, next) {
          // 执行此函数时,实例还没创建完成,所以不能使用this,但在next执行时可以接收一个参数,指代当前实例
          // 也可以把vm当作this来使用
          console.log('这是组件内部守卫:beforRouteEnter');
          next((vm) => {
              console.log('这是组件内部守卫:beforRouteEnter的next');
          });
      },
      beforeRouteUpdate(to, from, next) {
      	// 在当前路由改变,组件被复用时调用;路由和组件相同但参数变化;可以使用this
          console.log('这是组件内部守卫:beforRouterUpdate');
          next();
      },
      beforeRouteLeave(to, from, next) {
      	// 导航离开当前组件前调用,可以使用this
          console.log('这是组件内部守卫:beforRouterLeave');
          next();
      },
      beforeDestroy() {
          console.log('这是销毁前执行的方法:beforeDestroy');
      },
      destroyed() {
          console.log('这是销毁后执行的方法:destroyed');
      },
  }
  
  let list = {
      template: '<div>列表页</div>',
  }
       

配置路由映射表,path:指向路由路径,component:指向此路径关联的组件

const routes = [{
   path: "/home/:id",
    component: home,
    beforeEnter(to, from, next) {
        console.log('这是路由独享守卫:beforeEnter');
        next();
    }
}, {
    path: '/list',
    component: list
}]

// 创建VueRouter实例,并将routes添加到router中,作为router中的一个属性,可以在router-->options-->routes中查看
const router = new VueRouter({
    routes
})

全局守卫一个页面中可以创建多个,创建几个执行几次
只要页面的路由有变化就会触发beforeEach方法执行,当一个导航触发时,全局前置守卫按照创建顺序依次执行。守卫是异步解析执行的,此时导航在所有守卫resolve之前一直处于等待状态。
参数中的to:即将要进入的目标;from:当前正要离开的目标;
next:是一个回调函数,一定要调用该方法才能resolve这个钩子函数,执行效果依赖next方法调用的参数。

  • next():执行管道中的下一个钩子函数,如果全部钩子函数执行完,则导航的状态是commfirmed(确认)的。
  • next(false):中断当前的导航,如果浏览器的URL改变了(可能是手动或者浏览器后退按钮),那URL会重置到from路由对应的地址上。
  • next(/)或next({path:"/…"}):跳转到一个不同的地址,当前的导航被中断,执行next中传的导航。
  • next(error):如果next执行传入的参数是error的实例,则导航会被终止该错误会被传递给router.onError()注册过的回调。
 // 创建全局前置守卫
router.beforeEach((to, from, next) => {
  console.log('这是全局前置守卫:beforeEach');
    next();
})
router.beforeEach((to, from, next) => {
    console.log('这是全局前置守卫:beforeEach');
    next();
})

router.afterEach((to, from) => {
    console.log('这是全局的后置守卫:afterEach');
})

beforeResolve是2.5.0新增的方法,和beforeEach类似,区别是:在导航确认之前,同时所有的组件内守卫和异步路由组件都被解析之后,beforeResolve才会执行

router.beforeResolve((to, from, next) => {
   console.log('这是全局解析守卫:beforeResolve');
    next();
})

将router在全局vue实例中注册

let vm = new Vue({
	el: '#app',
	   data: {},
	   router
});

本次测试没有配置默认显示组件,所以首次加载页面不会显示任何组件,需要点击后才会显示对应组件
以下是切换不同路由的执行结果,比较繁杂,可以直接跳过看结论

首次加载执行顺序:可以忽略,主要的是下面几次点击后的执行结果

这是全局前置守卫:beforeEach
这是全局前置守卫:beforeEach
这是全局解析守卫:beforeResolve
这是全局的后置守卫:afterEach

点击首页后执行顺序:

这是全局前置守卫:beforeEach
这是全局前置守卫:beforeEach
这是路由独享守卫:beforeEnter
这是组件内部守卫:beforRouteEnter
这是全局解析守卫:beforeResolve
这是全局的后置守卫:afterEach
这是实例创建前执行的方法:beforeCreate
这是实例创建后执行的方法:created
这是挂载前执行的方法:beforeMount
这是挂载后执行的方法:mounted
这是组件内部守卫:beforRouteEnter的next

从首页切换到首页1执行顺序:

这是beforeEach全局前置守卫
这是beforeEach全局前置守卫
这是组件内部的beforRouterUpdate守卫
这是beforeResolve全局解析守卫
这是afterEach全局的后置守卫
由于首页和首页1是共用的一个组件和路由只是参数不同,所以组件会被复用,不会触发生命周期钩子函数,路由改变会触发组件内的导航守卫钩子函数

从首页1切换到列表页执行顺序:

这是组件内部的beforRouterLeave守卫
这是beforeEach全局前置守卫
这是beforeEach全局前置守卫
这是beforeResolve全局解析守卫
这是afterEach全局的后置守卫
这是销毁前执行的方法
这是销毁后执行的方法

从首页/首页1切换到列表页,组件和路由都不同,首页的组件会被销毁,所以会触发声明周期销毁的钩子函数,如果再从列表页切换到首页/首页1,组件会被重新创建,所以会触发生命周期创建和挂载的钩子函数

图示:图片实例中不包含vue实例生命周期的钩子函数
VueRouter导航守卫图示

结论

全局守卫可以在页面中多次创建,且创建多少次执行多少次
vue实例是在导航守卫都执行完成才进行创建的
复用同一组件只有参数不同,切换跳转不会触发实例声明周期的beforeDestroy和destroyed钩子函数
非复用同一组件,切换跳转,from的组件会触发beforeDestroy和destroyed钩子函数,再次切换回来会触发beforeCreate、created、beforeMount和mounted钩子函数
beforeResolve解析守卫会在所有组件守卫和异步路由组件解析完成后,afterEach执行前被触发执行
next中的回调函数会在实例创建完成后执行

注意:虽然导航守卫可以让我们在组件加载前做一些操作,尤其是异步操作,可以避免加载完毕却没有获取到数据的显示空白页面的尴尬,但是,在组件加载前进行过多操作,会导致页面加载速度慢,也同样不是一个好的用户体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值