vue使用vue-router beforEach实现判断用户登陆跳转路由筛选

尊重我的原创,转载请注明出处。

需求

在开发webApp的时候,考虑到用户体验,常常会把不须要调用我的数据的页面设置成游客能够访问,而当用户进入到一些须要我的数据的,例如购物车,我的中心,个人钱包等等,在进行登陆的验证判断,若是判断已经登陆,则显示页面,若是判断未登陆,则直接跳转到登陆页面提示用户登陆,今天就来分享下如何使用vue-router的beforEach方法来实现这个需求。vue

实现

本篇文章默认您已经会使用webpack或者vue-cli来进行环境的搭建,而且具备必定的vue基础,若是您目前是一个新手,那么网上搜索一下就好,相关文章很是多,这里就再也不赘述了。 话很少说,直接上代码。 为了方便往后代码的可维护性,我把相关方法写在了一个新建的filter.js文件里webpack

接下来进入filter.js文件中,首先引入vue-router:import router from "./router";而后咱们使用router.beforEach方法:ios

router.beforeEach((to, from, next) => {
    //根据字段判断是否路由过滤
    if (to.matched.some(record => record.meta.auth)) {
        if (getToken() !== null) {
            next()
        } else {
            //防止无限循环
            if (to.name === 'login') {
                next();
                return
            }
            next({
                path: '/login',
            });
        }
    } else {
        next()//若点击的是不须要验证的页面,则进行正常的路由跳转
    }
});
复制代码

beforEach实际上是vur-router的钩子函数,能够理解为每一个router跳转以前都会调用的一个方法,既然有before同理固然也有afterEach,这个咱们之后再讲。web

首先来解释下beforEach的三个参数:vue-router

  1. to:router即将进入的路由对象。
  2. from:当前导航正要离开的路由。
  3. next:一个function,必定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
  • next(): 进行管道中的下一个钩子。若是所有钩子执行完了,则导航的状态就是 confirmed (确认的)。
  • next(false): 中断当前的导航。若是浏览器的 URL 改变了(多是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
  • next('/') 或者 next({ path: '/' }): 跳转到一个不一样的地址。当前的导航被中断,而后进行一个新的导航。 你能够向 next 传递任意位置对象,且容许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在 router-link 的 to prop 或 router.push 中的选项,注意,next能够经过query传递参数。
  • next(error): (2.4.0+) 若是传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。

说明

好了,看到这里可能有些人仍是没有理解,不要紧,接下来我举个例子就能够明白了。
假设咱们目前有三个路由:/home,/mine,/login
咱们初始进入为/home,这时候点击跳转/mine,可是因为咱们没有登陆,因此会自动跳转到/login
在以上这种状况下,
to:表明着路由/mine,咱们要进入的路由。
from:表明着路由/home,咱们将要离开的路由。
注意,使用beforEach最后必需要调用next(),不然会报错,若是不传参数,咱们就会成功进入到/mine,若是咱们传递参数,例如next('/login'),那么咱们在点击任何路由都会跳转到/login界面。
可是咱们的需求是只有点击须要进行登陆验证的页面才进行拦截跳转,所以,咱们须要加一些判断条件来进行路由的筛选。vue-cli

if (to.matched.some(record => record.meta.auth)) {
        if (getToken() !== null) {
            next()
        }
    }
复制代码

这里的to就是上面讲的参数to,to.matched是一个对象数组,里面有to指向路由的相关信息,例如:path,name,meta等等。
咱们用该数组调用some()方法根据返回值true或者false来进行判断,因此咱们要在router.js路由配置文件中为咱们须要验证登陆判断跳转的路由添加一个字段来做为判断条件axios

{
      path: '/mine',
      name: 'mine',
      component: mine,
      meta:{auth:true}  //咱们本身添加的字段
    }
复制代码

因为给路由添加了meta:{auth:true},因此咱们的to.matched.some(record => record.meta.auth)会返回true,这时咱们就能够作登陆判断了,个人项目是经过把token存入到localstorage来进行判断的, getToken()是我封装的一个获取localstorage方法。后端

if (getToken() !== null) {
            next()//若token不为null,则进行路由跳转
        }
复制代码

若是没有token,咱们下一步继续进行判断,也就是最终目的,进行路由拦截,跳转到登陆页数组

else {
            next({
                path: '/login',
            });
        }
复制代码

可是这时候咱们会遇到新的问题,打开控制台会发现路由会无限的循环并最终崩溃,这是什么缘由呢?仔细阅读上文红色加粗,咱们能够理解为浏览器

  • next() 表示路由成功,直接进入to路由,不会再次调用router.beforeEach()
  • next({ path: '/login', }); 表示路由拦截成功,重定向至login,会再次调用router.beforeEach()

也就是说beforeEach()必须调用next(),不然就会出现无限循环
next() 和 next('xxx') 是不同的,区别就是前者不会再次调用router.beforeEach(),后者会。而因为咱们没有token,因此在从新调用router.beforeEach()后,会再次进入到

else {
            next({
                path: '/login',
            });
        }
复制代码

因此形成了无限循环,解决这个问题的方法也很简单,咱们在next({ path: '/login', });以前增长一个判断条件

if (to.name === 'login') {
                next();
                return
        }
复制代码

若是咱们to的定向路由name == 'login',则执行next();并return终止代码运行。

以上就是经过router.beforEach方法进行路由拦截了,咱们不只仅能够只作登陆判断,经过这个方法能够实现不少需求,只要是有关路由跳转的均可以,在下只是抛砖引玉,若是有哪里不对的地方或者有更好的方法能够直接在评论告诉我,很是感谢。

tips

2018.7.2
因为实际项目中不少界面都须要进行token的验证拦截,所以考虑后决定把过滤的方法设置在axios拦截器的http response 拦截器里,根据后端返回的错误码来判断是token过时或者无效之类的错误来进行跳转到登陆页面.

相关文章
相关标签/搜索