Vue ---动态路由的实现

302 阅读2分钟

前言

Vue 项目的动态路由大体可分为两种:

  1. 前端方面将路由都规定好,登录时根据用户角色权限来动态展示路由;

  2. 后端处理对应的数据,通过请求接口来获取当前用户对应权限的路由表。

本文所讲的是最近项目用到的,第二种方式,主要是利用 Vue Router 的一些相关功能实现后端主导的动态路由。

Vue Router 相关了解

全局前置守卫 ,可以使用 router.beforeEach 注册一个全局前置守卫:

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

当触发导航时,全局前置守卫按照创建顺序调用。

利用全局前置守卫的特性,在触发导航页面加载前,将当前用户所用到的路由表通过 router.addRoutes 方法添加到 Router 实例中。

具体实现

  1. 根据和后端商定的数据格式封装一个处理返回的路由表的方法
import Layout from '@/layout'

export function generateRouteList(list) {
  const result = []
  list.map(item => {
    const obj = {
      path: item.url,
      meta: { title: item.display_name },
      name: item.name,
      hidden: !!item.hidden
    }
    if (item.component === 'Layout') {
      obj.component = Layout
    } else {
      const str = item.component && item.component.replace('@/views', '')
      obj.component = resolve => require([`../views${str}`], resolve)
    }
    if (item.child.length !== 0) {
      obj.children = generateRouteList(item.child)
    }
    result.push(obj)
  })
  return result
}
  1. 判断用户是否登录。

    如未登录,跳转登录页面;

    若已登录,判断是否已获取路由列表,已获取则跳转对应路由页面,如未获取则请求接口获取并保存至 vuex

if('登录'){
  if (!store.getters.routeList.length) { // 判断是否已获取路由列表
      await store.dispatch('user/getMenu')
      router.matcher = createRouter(constantRoutes).matcher
      router.addRoutes(store.getters.routeList)
      next({ ...to, replace: true })
   }
   next()
} else {
  '去登录'
}

常见问题

动态路由配合路由懒加载

  1. 使用 import() 的话,不能传入变量,不然编译时能确定从哪里找到文件模块

    可以使用模板字符串的方法,但在本项目中因为项目配置的 eslint 的一些规则,无法使用import 结合模板字符串的方法,最终通过查阅,采用了 require 实现懒加载的方法,使用 require 时在拼接路径时也必须把基本路径确定下来,因为需要提供部分信息 webpack 才能编译。

  2. 动态路由刷新后404

    其原因是在拼接基本静态路由和动态生成路由时,没有将404页面的匹配规则放置在路由表最后。