基于Vue的addRoutes实现权限控制

前言

从今年3月到现在入门前端也已经有两个月了,这两个月在自学的过程中遇到了许多问题也解决了其中一部分,但是现在才开始意识到把学习过程的问题整理到CSDN上。最近老师布置了基于Vue的权限控制,网上查阅了许多博客,例如“前端路上":这篇文章提到了Vue2.0以上使用的addRoutes增加动态路由的思路。然而我只是一个小白,尽管文章里贴出了源码,我也只能看的一知半解,所以根据文章中提供的思路自己写了一个小测试demo。

目录结构

准备工作

在路由配置文件里写上两个路由表,一个静态路由表(所有权限用户均能访问如“登录”、“404页”)和一个动态路由表,默认导出静态路由。

const router = new Router({ //静态路由,登录、404
  mode:'history',
  routes: [
    {
      path: '/login', //登录页
      name: 'login',
      component: (resolve) => require(['../components/login.vue'], resolve)
    },
    {
      path: '/404',  //404页
      name: 'err',
      component: (resolve) => require(['../components/err.vue'], resolve)
    },
  ]
});
export default router //默认静态路由
export const dynamicRouter =[ //动态路由
  {
    path: '/',
    name: 'home',
    meta: {  //添加meta标签,里面自定义了roles,用来设置权限
      roles:['admin','user']  //该路由仅admin和user权限访问
    },
    component: (resolve) => require(['../components/home.vue'], resolve)
  },
  {
    path: '/',
    name: 'home2',
    meta: {
      roles:['tourist'] //该路由仅tourist权限访问
    },
    component: (resolve) => require(['../components/home2.vue'], resolve)
  },
  {
    path: '/home21',
    name: 'home21',
    meta: {
      roles:['user']
    },
    component: (resolve) => require(['../components/home21.vue'], resolve)
  },
  {
    path: '/home11',
    name: 'home11',
    meta: {
      roles:['admin']
    },
    component: (resolve) => require(['../components/home11.vue'], resolve)
  },
];

这里我们已经配置好了路由表。

思路

如果用户没有登录,那就将页面重定向到“/login”,实现方法:在跟组件(App.vue)的created回调里做判断

methods:{
    judgelogin(){ //methods写一个判断是否登录的方法
      let isLogin = store.state.token; //这里我们从Vuex里取出token,因为登录请求成功后我们会将后台返回的token存储在vuex里方便使用
      if(!isLogin){ //如果没有token,那就代表用户没有登录
        return this.$router.push('/login'); //重定向到login页
      } 
    }
  },
created() {
     this.judgelogin(); //在created里调用上面构造的方法
  }

登录页:

HTML:
template>
  <div id="login">
    <form>
      <label>账号</label><input type="text" v-model="username"/><br>
      <label>密码</label><input type="password" v-model="password"/><br>
      <input type="button" value="登录" @click="Login">
    </form>
  </div>
</template>
JS:
import {router,dynamicRouter} from '../router/index' //获取路由配置文件里的两个路由表

export default {
  name: 'login',
  data () {
    return {
      username:'', //双向绑定获取账号
      password:'', //双向绑定获取密码
    }
  },
  methods:{
    Login(){
      sessionStorage.setItem('token',this.username); //将token和roles保存下来,因为没有后台接口,我这边就将账号当做token和roles
      sessionStorage.setItem('roles',this.username);
      let dR = new Array(); //创建一个数组用来存储符合权限的路由
      for (let i=0;i<dynamicRouter.length;i++){ //第一层循环遍历动态路由表的每一个路由
        for (let j=0;j<dynamicRouter[i].meta.roles.length;j++){ //第二次循环遍历每一个路由里的roles设置的权限并和当前登录账号的权限比较
          if (dynamicRouter[i].meta.roles[j] == this.username){ //这里因为我默认账号名就是当前用户的权限
           dR.push(dynamicRouter[i]); //符合条件的路由信息就放进数组里
         }
        }
      }
      this.$router.addRoutes(dR.concat([{ //这里调用addRoutes方法,动态添加符合条件的路由
        path: '*',
        redirect: '/404' //所有不匹配路径(*)都重定向到404,为什么写在这里而不放到静态路由表里可以查看“前端路上”的文章
      }]));
      this.$router.push('/'); //登录验证后跳转到主页"/"
    }
  },
  created(){
    sessionStorage.clear(); 
  }
}

到这里我们用账号“admin”登录后就可以成功跳转到主页并显示"home.vue"的内容,我们也可以修改url访问"/home11"。但是当我们访问"/home2"和"/home21"的时候没有出现我们预期的跳转到"/404"页,这里出了一个bug不知道为什么,希望用大神能够指正出来,小弟感激不尽!

前方有坑:

登陆后,当我们按"F5"键刷新页面后,页面内容都消失不见了(理论上应该是/404页内容)。原来addRoutes和Vuex一样都是刷新后数据会清空(这个地方我感觉是真的坑)。这是因为刷新会导致Vue重新实例化,路由也恢复到了初始路由,也就是前面的静态路由表。

改进:

在根组件的created回调里,我们不仅得判断用户是未登录状态还是登陆后又刷新,改进代码如下

judgeLogin(){
      let isLogin = store.state.token;
      if(!isLogin){
        return this.$router.push('/login');
      } else {
        let dR = new Array();
        for (let i=0;i<dynamicRouter.length;i++){
          for (let j=0;j<dynamicRouter[i].meta.roles.length;j++){
            if (dynamicRouter[i].meta.roles[j] == store.state.roles){
              dR.push(dynamicRouter[i]);
            }
          }
        }
        this.$router.addRoutes(dR);
      }
    }

这样即使刷新,你生成的动态路由也不会失效了。

附上:

因为是小测试,所以Vuex里只存了两个数据:

export default new Vuex.Store({
  state:{
    token:sessionStorage.getItem('token'), 
    roles:sessionStorage.getItem('roles'),
  },
})

结:

第一次写博客还是有点激动的,不知道这个权限控制思路能不能对大家有所帮助。这样的权限控制其实分不同权限写了几套页面,然后根据权限动态添加符合权限的页面。其实我一开始的设想是一个主页的菜单栏根据不同权限的用户显示不同的导航(这个实现效果看“前端路上”大能分享的github上源码),但是技术有限还未能实现,后续实现后会贴出来的。


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页