vue 实现动态路由

Posted 前端~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue 实现动态路由相关的知识,希望对你有一定的参考价值。

vue-router对象中的addRoutes,用它来动态添加路由配置

格式:

router.addRoutes([路由配置对象])
this.$router.addRoutes([路由配置对象])

举个例子:

// 按钮
<button @click="hAddRoute">addRoute</button>

// 回调
hAddRoute() 
    this.$router.addRoutes([
        path: '/abc',
        component: () => import('@/views/abc'),
        ])
,

我是以 vue-admin-template 为例,做如下演示:

在router/index.js中的路由配置中 只保留静态路由(因为我们要动态的添加))

const createRouter = () => new Router(
  // mode: 'history', // require service support
  scrollBehavior: () => ( y: 0 ),
  routes: [...constantRoutes]   //因为要动态添加动态路由,所以这里只写静态路由
)

在permission.js中引入,并使用addRoutes动态添加

这个是 router 下的 index.js中定义的 静态路由、动态路由

接下来来看 在permission.js中引入的内容,

// 引入所有的动态路由表(未经过筛选)
+ import router,  asyncRoutes  from '@/router'

const whiteList = ['/login', '/404']
router.beforeEach(async(to, from, next) => 
  // 开启进度条
  NProgress.start()
  // 获取本地token 全局getter
  const token = store.getters.token
  if (token) 
    // 有token
    if (to.path === '/login') 
      next('/')
     else 
      if (!store.getters.userId) 
        await store.dispatch('user/getUserInfo')
        // 改写成动态添加的方式
+       router.addRoutes(asyncRoutes)
      
      next()
    
   else 
    // 没有token
    if (whiteList.includes(to.path)) 
      next()
     else 
      next('/login')
    
  
  // 结束进度条
  NProgress.done()
)

如果我们希望在调用addRoutes方法之后,要路由数据立刻反映到菜单中,我们需要想一个额外的方法,思考一下,vue开发中,哪个技术可以保证响应式特性还可以动态修改? vuex!

补充模块,在src/store/modules下补充menu.js模块 (定义vuex管理菜单数据

import  constantRoutes  from '@/router' 
export default 
  namespaced: true,
  // 公共数据
  state: 
    // 本地取一下token
    menuList: [] // 所有可以访问的路由配置
  ,
  mutations: 
    setMenuList(state, asyncRoutes)  
      console.log('asyncRoutes', asyncRoutes) //第二个参数是调用mutatains时传过来的动态路由参数
      state.menuList = [...constantRoutes, ...asyncRoutes]
    
  

当然,要在 src/store/index.js 中注册这个模块

修改src/permission.js中的代码

if (!store.getters.userId) 
        await store.dispatch('user/getUserInfo')

        // 动态添加可以访问的路由设置
        router.addRoutes(asyncRoutes)

        // 根据用户实际能访问几个页面来决定从整体8个路由设置
        // 中,过滤中出来几个,然后保存到vuex中
    ++   store.commit('menu/setMenuList', asyncRoutes)  //把动态路由存入vuex中
      

在src\\layout\\components\\Sidebar\\index.vue文件中,修改

routes() 
  // 拿到的是一个完整的包含了静态路由和动态路由的数据结构
  return this.$store.state.menu.menuList

上一步我们实现了: 1.把动态路由通过addRoutes动态添加到了路由系统里, 2. 把动态路由保存到vuex的menu中,

但是我们没有和权限数据做搭配,接下来我们通过接口返回的权限数据对动态菜单做过滤处理,以确定完成菜单与用户权限相关。

接下来就是 调接口,后端返给你菜单数据:

用户能访问哪些页面是通过actions获取到的,只需要从action中返回即可

在permission.js中获取action的返回值并过滤

if (!store.getters.userId) 
        // 有token,要去的不是login,就直接放行
        // 进一步获取用户信息
        // 发ajax---派发action来做
        const menus = await store.dispatch('user/getUserInfo')
        console.log('当前用户能访问的页面', menus)
        console.log('当前系统功能中提供的所有的动态路由页面是', asyncRoutes)
        // 根据本用户实际的权限menus去 asyncRoutes 中做过滤,选出本用户能访问的页面

        const filterRoutes = asyncRoutes.filter(route => 
          const routeName = route.children[0].name
          return menus.includes(routeName)
        )

        // 一定要在进入主页之前去获取用户信息

        // addRoutes用来动态添加路由配置
        // 只有在这里设置了补充了路由配置,才可能去访问页面
        // 它们不会出现左侧
        router.addRoutes(filterRoutes)

        // 把它们保存在vuex中,在src\\layout\\components\\Sidebar\\index.vue
        // 生成左侧菜单时,也应该去vuex中拿
        store.commit('menu/setMenuList', filterRoutes)
      

问题

如果我们刷新浏览器,会发现跳到了404页面

对于addRoute添加的路由,在刷新时会白屏

原因

现在我们的路由设置中的404页处在中间位置而不是所有路由的末尾了。

解决

把404页改到路由配置的最末尾就可以了

 filterRoutes.push( path: '*', redirect: '/404', hidden: true ) 
//解决刷新去404页面
 // 解决刷新出现的白屏bug
  next(
    ...to, // next( ...to )的目的,是保证路由添加完了再进入页面 (可以理解为重进一次)
    replace: true // 重进一次, 不保留重复历史
  )

效果如下:

Vue实现动态路由

参考技术A

通常我们在vue项目中都是前端配置好路由的,但在一些项目中我们可能会遇到权限控制,这样我们就涉及到 动态路由 的设置了。

动态路由设置一般有两种

(1)、简单的角色路由设置:比如只涉及到管理员和普通用户的权限。通常直接在前端进行简单的角色权限设置

(2)、复杂的路由权限设置:比如OA系统、多种角色的权限配置。通常需要后端返回路由列表,前端渲染使用

到这里,整个动态路由就可以走通了,但是页面跳转、路由守卫处理是异步的,会存在动态路由添加后跳转的是空白页面,这是因为路由在执行next()时,router里面的数据还不存在,此时,你可以通过window.location.reload()来刷新路由
后端返回的路由格式:

注意: vue是单页面应用程序,所以页面一刷新数据部分数据也会跟着丢失,所以我们需要将store中的数据存储到本地,才能保证路由不丢失。关于vue页面刷新保存页面状态,可以查看 vue如何在页面刷新时保留状态信息

以上是关于vue 实现动态路由的主要内容,如果未能解决你的问题,请参考以下文章

[JavaScript从入门到放弃系列] 高级篇10.是时候用Vue.js来写前端了(路由1)

Vue.js 前端路由与后端烧瓶路由冲突

面试需要-Vue全家桶一文带你看透Vue前端路由

Vue.js 中的动态路由

vue.js 中用于导航到动态路由的动态按钮

Vue小模块之功能全面的表格实现带有数组输入的表单