Vue3 根据路由动态生成Menu左侧菜单栏

根据下面步骤写动态路由左菜单,直接套用就可用。后面请求接口直接渲染即可。

效果图:

1、首先,我们先新建一个menu文件

<template>
  <div>
    <template v-for="(item, index) in menuList" :key="item.path">
      <!-- 没有子路由 -->
      <template v-if="!item.children">
        <el-menu-item :index="item.path" v-if="!item.meta.hidden">
          <template #title>
            <!-- 图标 -->
            <el-icon>
              <component :is="item.meta.icon"></component>
            </el-icon>
            <span>{
   
   { item.meta.title }}</span>
          </template>
        </el-menu-item>
      </template>

      <!-- 有子路由,但只有一个子路由 -->
      <template v-if="item.children && item.children.length == 1">
        <el-menu-item
          v-if="!item.children[0].meta.hidden"
          :index="item.children[0].path"
        >
          <template #title>
            <!-- 图标 -->
            <el-icon>
              <component :is="item.children[0].meta.icon"></component>
            </el-icon>
            <span>{
   
   { item.children[0].meta.title }}</span>
          </template>
        </el-menu-item>
      </template>

      <!-- 有子路由,并且大于一个 -->
      <el-sub-menu
        :index="item.path"
        v-if="item.children && item.children.length > 1"
      >
        <template #title>
          <!-- 图标 -->
          <el-icon>
            <component :is="item.meta.icon"></component>
          </el-icon>
          <span>{
   
   { item.meta.title }}</span>
        </template>
        <!-- 路由递归 : 二级路由还有子路由,子路由又还有子路由-->
        <Menu :menuList="item.children"></Menu>
      </el-sub-menu>
    </template>
  </div>
</template>

<script lang="ts" setup>
import { reactive, toRefs, ref } from 'vue'

// 获取父组件传递过来的全部路由数组
defineProps(['menuList'])
</script>

<!-- 递归的 -->
<script lang="ts">
export default {
  name: 'Menu',
}
</script>

<style lang="scss" scoped></style>

2、新建路由

export const constantRoute = [
  {
    path: '/login',
    component: () => import('@/views/login/index.vue'),
    name: 'login',
    meta:{
      title:'登录',
      hidden:true,
      icon:'Promotion'
    }
  },
  {
    path: '/',
    component: () => import('@/layout/index.vue'),
    name: 'layout',
    meta:{
      title:'layout',
      hidden:false,
      icon:'Avatar'
    },
    redirect:'/home',
    children:[
      {
        path:'/home',
        component:()=>import('@/views/home/index.vue'),
        meta:{
          title:'首页',
          hidden:false,
          icon:'HomeFilled'
        }
      },
      {
        path:'/home',
        component:()=>import('@/views/home/index.vue'),
        meta:{
          title:'测试',
          hidden:false,
          icon:'HomeFilled'
        }
      },
    ]
  },
  {
    path: '/404',
    component: () => import('@/views/404/index.vue'),
    name: '404',
    meta:{
      title:'404',
      hidden:true,
      icon:'DocumentDelete'
    }
  },
  {
    path: '/:pathMatch(.*)*',
    redirect: '/404',
    name: 'Any',
    meta:{
      title:'任意路由',
      hidden:true,
      icon:'DataLine'
    }
  },
]

3、新建一个仓库store,将导出的路由存在仓库里

import {constantRoute} from '@/router/routes' //引入

let userUserStore = defineStore('User', {
    // 仓库
    state: ():UserState => {
        return {
            token:GET_TOKEN()!,  //token
            menuRoutes:constantRoute, //存储menu菜单(路由)
        }
    },
    // 异步|逻辑
    actions: {
        
    },
    getters: {

    }
})

export default userUserStore

4、在要用到的layout布局页面,引入使用menu文件、引入仓库获取数据

<template>
  <div class="layout_container">
    <div class="layout_slider">
      <Logo />
      <el-scrollbar class="scrollbar">
        <el-menu background-color="#001529" text-color="#fff">
          <!-- 根据路由动态生成菜单 -->
          <Menu :menuList='userStore.menuRoutes'></Menu>
        </el-menu>
      </el-scrollbar>
    </div>
    <div class="layout_tabber">456</div>
    <div class="layout_main">
      <p style="height: 100vh">13123213</p>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import Logo from './logo/index.vue'
import Menu from './menu/index.vue'

// 获取仓库数据
import userUserStore from '@/store/modules/user';
let userStore = userUserStore()


</script>

5、注册全局图标,在component 文件下,新建index.ts,关于使用menu、和路由中可以看到

// 引入项目中全部的全局组件
import SvgIcon from './Svgicon/index.vue'
import Pagination from './Pagination/index.vue'
// 全局引入icon图标
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

// 全局对象
const allGloablComponent: any = {
  SvgIcon,
  Pagination,
}

export default {
  // 务必叫做install方法
  install(app: any) {
    // 注册为全局组件
    Object.keys(allGloablComponent).forEach((key) => {
      app.component(key, allGloablComponent[key])
    });
    // icon图标
    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
      app.component(key, component)
    }
  },
}

6、main.ts引入全局组件

// 引入自定义插件对象:注册整个项目全局组件
import gloalComponent from '@/components'
// 安装自定义插件
app.use(gloalComponent)

上一篇是关于注册 iconfont 注册为全局组件

猜你喜欢

转载自blog.csdn.net/xfy991127/article/details/135831196