提示

其实当前内容是对前面《二、界面控制的补充》

# 路由表

  前端根据 roles 去向后端请求可访问的路由表,然后将后端返回路由表和本地的组件映射到一起

{
  "rights": [
    {
      "id": 103,
      "authName": "⻆⾊管理",
      "icon": "icon-tijikongjian",
      "componentName": "roles",
      "children": [
        {
          "id": 111,
          "authName": "⻆⾊列表",
          "path": "rolesList",
          "componentName": "rolesList",
          "rights": ["view", "edit", "add", "delete"]
        }
      ]
    },
    {
      "id": 101,
      "authName": "商品管理",
      "icon": "icon-shangpin",
      "componentName": "goods",
      "children": [
        {
          "id": 104,
          "authName": "商品列表",
          "path": "goodsList",
          "componentName": "goodsList",
          "rights": ["view", "edit", "add", "delete"]
        },
        {
          "id": 121,
          "authName": "商品分类",
          "path": "categories",
          "componentName": "categories",
          "rights": ["view", "edit", "add", "delete"]
        }
      ]
    }
  ]
}

# 一、动态路由

# 1、结构

├── router
    ├── index.js
    ├── limits.js        # 路由控制

# 2、路由信息

注意

关于菜单栏的动态路由实现,前提是一定要有一个 children

当前我们的仅仅是解决了二级路由,如果后端传来一级路由、多级路由就呵呵了 😂。

终极方案:可以参考 vue-element-admin 的动态路由实现

  • router/index.js
const routes = [
  {
    path: '/',
    name: '首页',
    component: () => import('../layout'),
    redirect: '/dashboard',
    children: [
      // 登录初次显示
      {
        path: '/dashboard',
        name: '首页',
        component: () => import('../views/index/index')
      },
      // 其他动态路由的存放位置
      // ……
    ]
  },
  {
    path: '/login',
    component: () => import('@/views/login/index'),
  },

  {
    path: '/404',
    component: () => import('@/views/404'),
  }
  { path: '*', redirect: '/404', hidden: true }
]

const router = createRouter({
  routes
})

export default router

# 二、核心实现

  • main.js
// 全局使用
import '@/router/limits.js'
  • router/limits.js
import router from '@/router/index'
import store from '@/store'

// 一、导航守卫
const whiteList = ['/login', '/register']

router.beforeEach((to, from, next) => {
  if (whiteList.includes(to.path)) {
    next()
  } else {
    const token = sessionStorage.getItem('token')
    if (!token) {
      next('/login')
    } else {
      next()
    }
  }
})

# 方式 1:映射

优点:

component 的命名归前端管理,不用担心与后端命名不一致的问题

缺点:

不方便,要手动写路由规则

// 二、动态路由
// 1、菜单对象转路由对象
// 路由规则
const userRule = { path: '/users', component: Users }
const roleRule = { path: '/roles', component: Roles }
const goodsRule = { path: '/goods', component: GoodsList }
const categoryRule = { path: '/categories', component: GoodsCate }

// 登录请求path路由 与 路由规则 的映射🚩
const ruleMapping = {
  users: userRule,
  roles: roleRule,
  goods: goodsRule,
  categories: categoryRule
}

// 2、动态绑定路由
// 根据用户权限,设置动态路由规则
export function initDynamicRoutes() {
  console.log(router)
  // 路由中定义的【基础路由】(数组✨)
  const currentRoutes = router.options.routes

  // 服务器返回的数据(json数据)
  const rightList = $store.state.rightList
  rightList.forEach((item) => {
    // 获取其中children的【二级路由】(数组✨)
    item.children.forEach((menu) => {
      // ①、动态添加二级路由🚩
      const temp1 = ruleMapping[menu.path]

      // ②、动态添加按钮权限
      temp1.meta = menu.rights // 利用路由元信息附加上权限信息(备用👏)

      currentRoutes[0].children.push(temp1) // 这里的下标要将动态路由存放的位置
    })
  })

  // 正式重置路由
  currentRoutes.forEach((item) => {
    router.addRoutes(item)
  })
}

# 方式 2:函数封装

优点:

方便快捷

缺点:

component 命名归后端管理,前端要提前知道后端定义的 menu.component。

// 二、动态路由
// 1、菜单对象转路由对象
const menuToRoute = (item, menu) => {
  let route = {
    name: menu.authName,
    path: menu.path,
    component: () => import(`@/views/${item.component}/${menu.component}.vue`)
    meta: {
      // ②、动态添加按钮权限
      rights: menu.rights // 利用路由元信息附加上权限信息(备用👏)
    }
  }
  return route
}

// 2、动态绑定路由
// 根据用户权限,设置动态路由规则
export function initDynamicRoutes() {
  console.log(router)
  // 路由中定义的【基础路由】(数组✨)
  const currentRoutes = router.options.routes

  // 服务器返回的数据(json数据)
  const rightList = $store.state.rightList
  rightList.forEach((item) => {
    // 获取其中children的【二级路由】(数组✨)
    item.children.forEach((menu) => {
      // ①、动态添加二级路由🚩
      const temp1 = menuToRoute(item, menu)

      currentRoutes[0].children.push(temp1) // 这里的下标要将动态路由存放的位置
    })
  })

  // 正式重置路由
  currentRoutes.forEach((item) => {
    router.addRoutes(item)
  })
}

# 三、模块化应用

  参考:花裤衩之登录鉴权 (opens new window)

更新于 : 8/7/2024, 2:16:31 PM