首頁 > 軟體

如何利用Vue3管理系統實現動態路由和動態側邊選單欄

2022-02-16 10:01:03

前言

在做Vue管理系統的時候,都會遇到的一個需求:每個使用者的許可權是不一樣的,那麼他可以存取的頁面(路由),可以操作的選單選項是不一樣的,如果由後端控制,我們前端需要去實現動態路由,動態渲染側邊選單欄。

動態路由

  • 在本範例管理系統中,由於每個使用者的許可權不一樣,擁有的可以存取的路由頁面也不一樣,使用者能存取的路由頁面都是後端根據許可權動態設定的
  • 我們前端需要根據後端介面返回的路由表去動態增刪路由,從而生成這個使用者所擁有的路由。

重點:實現動態路由api

  • router.addRoute() //應用程式已經執行的時候新增路由
  • router.removeRoute() // 應用程式已經執行的時候刪除路由

定義共用的頁面路由(無論哪個使用者都會有的)

如無論什麼使用者都可存取登入頁login,錯誤頁面404。

import { createRouter, createWebHashHistory } from 'vue-router'

const publicRoutes = [
  {
    path: '/',
    redirect: { path: '/login' }
  },
  {
    path: '/login',
    name: 'login',
    component: () => import('../views/login')
  },
  {
    path: '/404',
    name: '404',
    component: () => import('../views/404')
  },
  {
    path: '/home',
    name: 'home',
    component: () => import('../views/home'),
    redirect: '/welcome',
    children: [
      {
        path: '/:pathMatch(.*)*',    // 捕獲所有路由或 404 Not found 路由
        component: () => import('../views/welcome')
      }
    ]
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes: publicRoutes
})

export default router

介面資料:這裡模擬介面的路由資料(這裡進行資料精簡,便於演示,實際情況可能要進行資料結構格式的轉換)

navigationList : [
     {
        id: 1,
        icon: 'icon-jurassic_user',
        name: '使用者管理',
        url: '/user'
    },
     {
        id: 2,
        icon: 'icon-jurassic_user',
        name: '角色管理',
        url: '/role'
     },
     {
        id: 3,
        icon: 'icon-shebei',
        name: '裝置管理',
        url: '/device'
      }
]

新增動態路由進去的時機(router.beforeEach)

利用全域性前置守衛router.beforeEach,在跳轉路由前先判斷是否已經新增過動態路由了,如果沒有,則先獲取資料進行新增路由。(router.beforeEach也會做登入等攔截,這裡省略)

import store from '@/store'
//這裡我用vuex的一個變數 asyncRoutestMark 來標識是否拼接過路由
router.beforeEach((to, from, next) => {
    if (!store.state.asyncRoutestMark) {
        // navigationList 是上面模擬介面返回的資料
        // 這裡將新的路由都作為 home 的子路由(實際開發根據情況)
        // meta 是儲存一些資訊,可以用於許可權校驗或其他
        navigationList.forEach( navigation => {
          router.addRoute('home', {
            path: navigation.url,
            meta: { name: navigation.name, isAsync: true, icon: navigation.icon },
            name: menu.url,
            component: () => import(`../views/${menu.url}`)
          })
        })
        console.log(router.getRoutes(), '檢視現有路由')
        store.commit('setAsyncRoutestMark', true) // 新增路由後更改標識為true
        next({ ...to, replace: true })     //路由進行重定向放行
    } else {
      next()
    }
})

利用router.getRoutes()方法檢視現有路由,我們將會看到根據新的路由新增進去了。

這樣我們就實現了動態路由啦!

動態側邊選單欄

  • 這是我們要實現的效果,根據介面資料動態渲染,不論層級多少都可以自動渲染,一級選單,二級選單,三級甚至更多(不過一般最多隻到三級哈哈)。

很多元件庫都可以實現這個功能,這裡我們將使用 Ant Design of Vue 元件庫的內嵌選單元件(如下圖)去實現,有父選單,子選單,父級選單的是用 a-sub-menu 包裹,子選單的是直接使用 a-menu-item,大家可以去看檔案看一下元件的使用。

介面資料:這裡模擬介面的選單資料(實際情況可能要進行資料結構格式的轉換)

menuList :[
  {
    url: '',
    name: '人員管理',
    icon: 'icon-renyuan',
    menuId: 1,
    children: [
      {
        url: '/user',
        name: '使用者管理',
        icon: 'icon-jurassic_user',
        menuId: 1001,
        children: []
      },
      {
        url: '/role',
        name: '角色管理',
        icon: 'icon-jiaose',
        menuId: 1002,
        children: []
      }
    ]
  },
  {
    url: '/device',
    name: '裝置管理',
    icon: 'icon-shebei',
    menuId: 2
  }
]

重點:元件遞迴

使用v-for迴圈選單資料陣列,渲染元件庫 ant design of vue的選單元件,這時分兩種情況,

  • 如果有children,那麼渲染a-sub-menu(父級選單),幷包裹自身元件,把children資料傳遞給呼叫的自身元件,也就是遞迴呼叫元件自身,那麼呼叫的自身元件就會重複上面邏輯的判斷,直到沒有children,也就是遇到了第二種情況,結束遞迴呼叫。
  • 如果沒有children,那麼直接顯示 a-menu-item (子選單)

下面為選單元件,元件名為MenuList,遞迴呼叫的時候要用到元件名,以達到根據不同資料渲染選單的情況

沒有圖示版本

<template>
  <template v-for="menu in menuList" :key="menu.menuId">
    <a-sub-menu v-if="menu.children && menu.children.length" :key="menu.menuId">
      <template #title>{{ menu.name }}</template>
      <MenuList :menuList="menu.children" />
    </a-sub-menu>
    <a-menu-item :key="menu.menuId" v-else>
      <span>{{ menu.name }}</span>
    </a-menu-item>
  </template>
</template>
<script setup>
import { defineProps } from 'vue'
defineProps({
  menuList: {
    type: Array,
    default: () => []
  }
})
</script>

效果如下

有圖示版本

圖示是根據介面資料的icon去匹配的,有多種方法,例如使用iconFont、svg、png,主要是去對應圖示的名字,這裡使用元件庫提供的使用icon的iconFont方法。

<template>
  <template v-for="menu in menuList" :key="menu.menuId">
    <a-sub-menu v-if="menu.children && menu.children.length" :key="menu.menuId">
      <template #icon>
        <icon-font :type="menu.icon" />
      </template>
      <template #title>{{ menu.name }}</template>
      <MenuList :menuList="menu.children" />
    </a-sub-menu>
    <a-menu-item :key="menu.menuId" v-else>
      <template #icon>
        <icon-font :type="menu.icon" />
      </template>
      <span>{{ menu.name }}</span>
    </a-menu-item>
  </template>
</template>
<script setup>
import { defineProps } from 'vue'
import { createFromIconfontCN } from '@ant-design/icons-vue'
const IconFont = createFromIconfontCN({
  scriptUrl: '//at.alicdn.com/t/font_2572336_4hg62uu7hxd.js'
})
defineProps({
  menuList: {
    type: Array,
    default: () => []
  }
})
</script>

效果如下:

這樣我們就實現了動態側邊選單欄啦!

總結

到此這篇關於如何利用Vue3管理系統實現動態路由和動態側邊選單欄的文章就介紹到這了,更多相關Vue3動態路由和動態側邊選單欄內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com