之前自学过vue-router,但都是停留在静态路由的层面,对于动态路由的实现一窍不通,刚好公司让维护一个使用了动态路由的项目,所以参照项目和网上的信息自己实现了一下,做个记录。

使用vuecli4.5创建的小项目,单纯实现动态路由,感兴趣可以戳https://github.com/shenxuekai/asyncrouter.git,或者git clone,说下项目配置:vue3 + ts + vue-router4.0 + vuex,4.0目前(2021-12-7)还是beta版本,比较适合vue3。至于vue2,最好搭配router3.x,网上有很多实现的例子,可以自行百度。

目前动态路由实现主要有两种方式:

1.前端定义好所有路由,登录时向后端请求权限码或者识别码,然后根据和后端约定好的方式对路由过滤,最后把过滤后的结果设置给router

2.前端只定义组件和界面,以及少部分路由,在登陆时像后端传递用户名/角色 后端返回该角色/用户对应的所有路由,前端接收到结果不需要再次过滤,稍微处理后就能使用

这里的实现方式类似第一种的简化版

先说下思路,首先构造一个静态路由,其次在登录界面 用户登录时对用户身份进行校验,如果满足某些条件则新增路由,最后将路由展示在home界面

目录结构:

1.构造静态路由:根据公共路由配置router并导出

import {createRouter, createWebHistory, RouteRecordRaw} from 'vue-router'
import baseRoutes from "@/router/baseRoutes";//格式同routes
import {asyncRoutes} from "@/router/asyncRoutes";//格式同routes
import store from "@/store";
const creatRouter =()=>{
  return createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes:baseRoutes
  })
}
let  router = creatRouter();

//重置路由:清空user 创建新的router store清空routes记录
export  function resetRouter():void {
  sessionStorage.setItem('user','')
  router = creatRouter()
  store.commit('set_allRoutes',[])
}
export default router

2.身份判断:在router.beforeEach守卫中进行判断,这个配置不一定必须写在router/index.ts中,可以单独创建

//前提:需要导入router store asyncRoutes(类似正常的routes对象) reset函数(用
//于重置路由,重置store仓库的值)
router.beforeEach(
    (to,from,next)=>{
//判断是不是要去首页,去首页的话就重置路由然后跳转
  if(to.path =='/login'||to.path==''){
    resetRouter()
    next()
    return
  }
//不是去首页的话,判断store仓库中的allroutes是不是有值了,如果有说明已经构造过了,就跳转

  if(store.state.allRoutes&&store.state.allRoutes.length>0){
    next()
  }else {
//没有构造过需要重新配置
//从sessionStorage中取出user,如果长度大于3就认为是管理员,新增管理路由
    const user: string | null = sessionStorage.getItem('user');
    if(user){
      if (user.length > 3) {
        for (const item of asyncRoutes) {
//vue-router4.0取消了addroutes方法,需要通过循环遍历异步路由表然后addroute添加
//注:权限判断条件可以自己改,也可以结合在异步路由表中添加meta.peimissionid的方式过滤路由
//发挥空间很大,这里只是提供了思路
          router.addRoute(item)
        }
      }
    }
//将更新后的路由提交给store,后续展示中组件会从store中取
    store.commit('set_allRoutes', router.getRoutes());
//这句话的意思:跳过这一次,重新验证 由于已经配置了routes,所以下一次直接跳转
    next({...to, replace: true});
  }
});

3.展示路由

创建navbar组件(在这里我使用了a标签而不是router-link,router-link实测有点问题,跳转manage显示空白页,手动刷新一次页面的话整个应用又正常了,很奇怪)

<template>
  <div>
    <a v-for="item in this.$store.state.allRoutes" :href="item.path"  :key="item" class="link">{{item.meta?item.meta.title:''}}</a>
  </div>
</template>

在Home中导入注册使用

4.结果展示:

当我们输入一个11,点击登录

 并且即使手动在导航栏输入http://localhost:8080/manage也不会显示,因为路由中不包含这一项

而当我们输入1111,点击登录

此时 不管是点击还是地址栏输入/manage,都可以访问到

附部分代码:

login.vue登录函数:

    handleLogin() {
      if(this.account.trim()){
        sessionStorage.setItem('user', this.account)
        this.$router.push('/home');//设置好user之后这里直接跳转,其他的交给路由导航守卫
      }else {
        alert("cuowu")
      }
    }

 store仓库:

import {createStore} from 'vuex'
const  state = {
    allRoutes:[],
    name:'shenxk'
};
const mutations = {
    set_allRoutes(state:any,payload:any){
        state.allRoutes = payload
    }
}
const options = {
    state,
    mutations
}
const  store = createStore(options)
export default store

源码请访问:https://github.com/shenxuekai/asyncrouter.git

Logo

前往低代码交流专区

更多推荐