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 注册为全局组件

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用 Vue Router 的嵌套路由来实现这个效果。具体步骤如下: 1. 在你的 Vue 项目中,打开路由文件(一般是 `router/index.js`)。 2. 创建一个父级路由用于容纳菜单栏和右边的页面。可以将其命名为 `MainLayout`(或任何你喜欢的名称)。 3. 在 `MainLayout` 路由下定义两个子路由:一个用于菜单栏,另一个用于右边的页面。 4. 在菜单栏的子路由中配置对应的组件,这个组件将会始终保持不变。 5. 在右边页面的子路由中配置对应的组件,这个组件将会根据路由变化而改变。 下面是一个示例代码: ```javascript // router/index.js import Vue from 'vue'; import Router from 'vue-router'; Vue.use(Router); const router = new Router({ routes: [ { path: '/', name: 'MainLayout', component: MainLayout, children: [ { path: 'menu', name: 'Menu', component: Menu, }, { path: 'page1', name: 'Page1', component: Page1, }, { path: 'page2', name: 'Page2', component: Page2, }, ], }, ], }); export default router; ``` 在上述代码中,`MainLayout` 是父级路由,`Menu` 组件是菜单栏的子路由,`Page1` 和 `Page2` 组件是右边页面的子路由。当你在浏览器中访问 `http://yourdomain.com/menu` 时,菜单栏的内容不变,右边页面显示 `Menu` 组件。当你访问 `http://yourdomain.com/page1` 时,菜单栏的内容不变,右边页面显示 `Page1` 组件。以此类推。 请注意,上述示例只是一种实现方式,具体根据你的项目需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值