[vue]导航守卫实用场景

156 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 19 天,点击查看活动详情

路由守卫使用场景

今天先总结一下,开发中路由守卫使用场景

1、路由拦截部分页面如果没有登录或者登录了但没有权限,不允许访问。

beforeEach(to, from, next), 可以拦截所有导航

// 已配置好了所有路由,给需要守卫的路由添加标记,判断是否有权限访问路由
router.beforeEach((to, from, next) => {
    // 路由是否需要守卫
  if (to.meta.auth) { 
    // 是否登录
    if (window.isLogin) { 
        // 如果登录了就放路由通行
        next() 
    } else { 
        // 没有登录时,终止当前导航,跳转到新的页面(登录页面),同时设置了redirect:登录后应该显示的页面地址
        next('/login?redirect='+to.fullPath) 
    } 
  } else { 
  // 无需守卫,即任何人都可以访问的页面,不需要控制页面权限的页面
    next() 
  }
})

2、进入路由后,也就是路由被激活时,这时导航尚未结束,组件未渲染时,想要获取服务器数据

  • breforeRouterEnter(to, from, next)

        breforeRouterEnter(to, from, next){
            // 导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航
            getData(to.params.id, post => { 
                next(vm => {
                    // 这里可以通过vm访问组件实例
                })
            })
            
        }
    

    注意:这时组件实例还没被创建,不能直接通过this 访问数据,但next的回调方法来访问实例

3、beforeRouterUpdate(to, from, next)的实用场景

beforeRouterUpdate钩子被执行时,代表组件被复用,这时导航未结束,组件已渲染,可以访问this
但路由变化但组件被复用时,声明周期钩子不会再重复调用
比如:使用动态路径参数或查询参数改变, 当参数改变beforeRouterUpdate会被调用, 这时如果想要根据参数获取服务器数据

beforeRouterUpdate(to, from, next) {
    this.post = null 
    getData(to.params.id, post => { 
        this.setData(post) //操作返回数据
        next()
    })
}

4、上面说的都是在导航前执行的;对应如果导航后想要获取服务器数据呢?

  • 使用组件内的生命周期钩子:created()
  • 组件被复用,生命周期钩子不会再次调用
    使用watch监听路由变化,获取数据。

动态添加路由

当需要控制路由权限时,上面提到了可以使用beforeEach拦截路由,使用beforeEach拦截时,首先所有路由都是已经配置;
那么如果说用户本来就没有访问某页面的权限,那能不能直接就不配置其路由?
可以通过router.addRoute添加一条新路由规则。如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。

router.beforeEach((to, from, next) =>{
    // 要求:登录后才能访问页面,如果没有登录强制跳转登录页
    if(window.isLogin){
        if(to.path === '/login'){
            next('/')
        }else {
            next()
        }
    }else {
        if(to.path === '/login'){
            next()
        }else {
            next('/login?redirect=' + to.fullPath)
        }
    }
})

登录后获取用户权限信息;动态添加某路由页面

login(){
  window.isLogin = true;
  this.$router.addRoute({
    path: '/ceshi',
    name: 'ceshi',
    component: () => import('./RouterHook.vue')
  });
  const redirect = this.$route.query.redirect || "/"; 
  this.$router.push(redirect);
}

路由组件缓存

利用keepalive做组件缓存,保留组件状态,提高执行效率

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
  • max - 数字。最多可以缓存多少组件实例。一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。

当组件在 内被切换,它的 activated 和 deactivated 这两个生命周期钩子函数将会被对应执行。

// about 是组件本身的名称
<keep-alive include="about"> 
    <router-view></router-view> 
</keep-alive>