• VUE 路由守卫 next() / next({ ...to, replace: true }) / next(‘/‘) 说明


    首先是路由守卫

    beforeEach((to, from, next) => {
        to // 要去的路由
        from // 当前路由
        next() // 放行的意思
    }

    但是在看别的项目时常常能看到next('/login') 、 next(to) 或者 next({ ...to, replace: true }) 
    其实在路由守卫中,只有next()是放行,其他的诸如:next('/login') 、 next(to) 或者 next({ ...to, replace: true })都不是放行,而是:中断当前导航,执行新的导航

    可以这么理解:

    next() 是放行,但是如果next()里有参数的话,next()就像被重载一样,就有了不同的功能。

    而对于上面说的中断当前导航,执行新的导航打个比方:

    现在我有一个守卫,在守卫中我使用next('/login'),肯定有同学认为是会直接跳转到/login路由:

    beforeEach((to, from, next) => {
      next('/login')
    }

    然而执行时需要这么看:

    beforeEach((to, from, next) => {
      beforeEach(('/login', from, next) => {
           beforeEach(('/login', from, next) => {
                beforeEach(('/login', from, next) => {
                    beforeEac...  // 一直循环下去...... , 因为我们没有使用 next() 放行
             }
          }
      }
    }

    如果把这个守卫改一下,当我在地址栏输入/home

    beforeEach((to, from, next) => {
       if(to.path === '/home') {
           next('/login')
       } else {
        // 如果要去的地方不是 /home , 就放行
           next()
       }
    }

    我本来要去/home路由,因此执行了第一次 beforeEach((to, from, next)

    但是这个路由守卫中判断了如果要去的地方是'/home',就执行next('/login')

    所以想要访问/home可以这么看

    beforeEach((to, from, next) => {
       beforeEach(('/login', from, next) => {
         next()  // 现在要去的地方不是 /home , 因此放行
       }
    }

    注意:重点就在这,next('/login')不是说直接去/login路由,而是中断(不是CPU的那个中断!VUE中的中断就是此时不会执行router.afterEach(() => {})这一次路由守卫的操作,又进入一次路由守卫,就像嵌套一样,一层路由守卫,然后又是一层路由守卫,此时路由守卫进入到第二层时,to.path已经不是/home了,这个时候才执行next()放行操作。


    正以为如此很多人在使用动态添加路由addRoutes()会遇到下面的情况:

    addRoutes()之后第一次访问被添加的路由会白屏,这是因为刚刚addRoutes()就立刻访问被添加的路由,然而此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。

    该如何解决这个问题 ?

    此时就要使用next({ ...to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去。
    next({ ...to, replace: true })中的replace: true只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。
    因此next({ ...to, replace: true })可以写成next({ ...to }),不过你应该不希望用户在addRoutes()还没有完成的时候,可以点击浏览器回退按钮搞事情吧。
    其实next({ ...to })的执行很简单,它会判断:
    如果参数to不能找到对应的路由的话,就再执行一次beforeEach((to, from, next)直到其中的next({ ...to})能找到对应的路由为止。
    也就是说此时addRoutes()已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next) ,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next),如果是,就执行next()放行。
    如果守卫中没有正确的放行出口的话,会一直next({ ...to})进入死循环 !!!
    因此你还需要确保在当addRoutes()已经完成时,所执行到的这一次beforeEach((to, from, next)中有一个正确的next()方向出口。

    因此想实现动态添加路由的操作的话,代码应该是这样的:

    router.beforeEach((to, from, next) => {
     const token = sessionStorage.getItem('access_token')
     // 存在 token 说明已经登录
     if (token) {
       // 登录过就不能访问登录界面,需要中断这一次路由守卫,执行下一次路由守卫,并且下一次守卫的to是主页'
       if (to.path === '/login') {
         next({ path: '/' })
       }
       // 保存在store中路由不为空则放行 (如果执行了刷新操作,则 store 里的路由为空,此时需要重新添加路由)
       if (store.getters.getRoutes.length || to.name != null) {
         //放行
         next()
       } else {
         // 将路由添加到 store 中,用来标记已添加动态路由
         store.commit('ADD_ROUTER', '需要添加的路由')
         router.addRoutes('需要添加的路由')
         // 如果 addRoutes 并未完成,路由守卫会一层一层的执行执行,直到 addRoutes 完成,找到对应的路由
         next({ ...to, replace: true })
       }
     } else {
       // 未登录时,注意 :在这里也许你的项目不只有 login 不需要登录 ,register 等其他不需要登录的页面也需要处理
       if (to.path !== '/login') {
         next({ path: '/login' })
       } else {
         next()
       }
     }

    万一还是听不懂,也可以next()比作Java Filter里的chain.doFilter(req, resp)

    @WebFilter(filterName = "EncodingFilter", urlPatterns = "/*")
    public class EncodingFilter implements Filter {
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            // 设置编码
            req.setCharacterEncoding("utf-8");
            resp.setContentType("text/html;charset=utf-8");
            chain.doFilter(req, resp);  // next()
        }
    
    }
  • 相关阅读:
    在Win8下无法打开 hlp 帮助文件的问题
    ftp 终端命令
    为 Macbook 增加锁屏热键技巧
    苹果系统直接读写 ntfs 磁盘
    div 绝对布局居中
    2015-1-11
    unable to load default svn client
    ubuntu eclipse 安装svn
    centos mysq table is read only
    centos ssh 乱码
  • 原文地址:https://www.cnblogs.com/windok/p/14549677.html
Copyright © 2020-2023  润新知