vue3+ts+vite递归组件生成菜单

首先需要将自己的组件创建好

配置路由

/router/routes.ts

// 对外暴露配置路由(常量路由)
export const constantRoute = [{
    // 登录
    path: '/login',
    component: () => import('@/views/login/index.vue'),
    name: 'login',  // 命名路由
    meta: {
        // 菜单标题 
        title: '登录',
        // 代表路由标题在菜单中是否隐藏
        hidden: true,
    }
}, {
    // 登录成功以后展示数据的路由
    path: '/',
    component: () => import('@/layout/index.vue'),
    name: 'layout',
    meta: {
        title: 'layout',
        hidden: false,
        icon: 'HomeFilled'
    },
    redirect: '/home',
    children: [{
        path: '/home',
        component: () => import('@/views/home/index.vue'),
        meta: {
            title: '首页',
            hidden: false,
            icon: 'HomeFilled'
        },
    }]
}, {
    path: '/screen',
    component: () => import('@/views/screen/index.vue'),
    name: 'Screen',
    meta: {
        title: '数据大屏',
        hidden: false,
        icon: 'Platform'
    }
}, {
    path: '/acl',
    component: () => import('@/layout/index.vue'),
    name: 'Acl',
    meta: {
        title: '权限管理',
        hidden: false,
        icon: 'Lock'
    }, 
    children: [{
        path: '/acl/user',
        component: () => import('@/views/acl/user.vue'),
        name: 'User',
        meta: {
            title: '用户管理',
            hidden: false,
            icon: 'UserFilled'
        },
    },{
        path: '/acl/role',
        component: () => import('@/views/acl/role.vue'),
        name: 'Role',
        meta: {
            title: '角色管理',
            hidden: false,
            icon: 'User'
        },
    },{
        path: '/acl/menu',
        component: () => import('@/views/acl/menu.vue'),
        name: 'Menu',
        meta: {
            title: '菜单管理',
            hidden: false,
            icon: 'Present'
        },
    }]
}, {
    path: '/goods',
    component: () => import('@/layout/index.vue'),
    name: 'Goods',
    meta: {
        title: '商品管理',
        hidden: false,
        icon: 'Watermelon'
    }, 
    children: [{
        path: '/goods/trademark',
        component: () => import('@/views/goods/trademark.vue'),
        name: 'Trademark',
        meta: {
            title: '品牌管理',
            hidden: false,
            icon: 'WindPower'
        },
    },{
        path: '/goods/attr',
        component: () => import('@/views/goods/attr.vue'),
        name: 'Attr',
        meta: {
            title: '属性管理',
            hidden: false,
            icon: 'Box'
        },
    },{
        path: '/goods/sku',
        component: () => import('@/views/goods/sku.vue'),
        name: 'Sku',
        meta: {
            title: 'sku管理',
            hidden: false,
            icon: 'FolderOpened'
        },
    },{
        path: '/goods/spu',
        component: () => import('@/views/goods/spu.vue'),
        name: 'Spu',
        meta: {
            title: 'spu管理',
            hidden: false,
            icon: 'ScaleToOriginal'
        },
    }]
}, {
    path: '/404',
    component: () => import('@/views/404/index.vue'),
    name: '404',
    meta: {
        title: '404',
        hidden: true
    }
}, {
    // 任意路由
    path: '/:pathMatch(.*)*',
    redirect: '/404',
    name: 'Any',
    meta: {
        title: '任意路由',
        hidden: true
    }
}]

/router/index.ts

// 通过vue-router插件实现模板吧路由配置
import {createRouter, createWebHashHistory} from 'vue-router';

import { constantRoute } from './routes';

// 创建路由器
let router = createRouter({
    // 路由模式hash
    history: createWebHashHistory(),
    routes: constantRoute,
    // 滚动行为
    scrollBehavior() {
        return {
            left: 0,
            top: 0
        }
    }
})

export default router;

将路由配置成功以后,将侧边栏菜单在需要填写菜单的位置用组件封装起来

<el-scrollbar class="scrollbar">
        <!-- 菜单组件 -->
        <el-menu
          class="el-menu-demo"
          background-color="#001529"
          text-color="#fff"
          active-text-color="#ffd04b"
          collapse
        >
          <Menu :menuList="userStore.menuRoutes"></Menu>
        </el-menu>
      </el-scrollbar>

menu自己封装的组件

<template>
  <template v-for="item in menuList" :key="item.path">
    <!-- 没有子路由 -->
    <el-menu-item
      :index="item.path"
      v-if="!item.children && !item.meta.hidden"
      @click="goRoute"
    >
      <el-icon>
        <component :is="item.meta.icon"></component>
      </el-icon>
      <template #title>
        <span>{{ item.meta.title }}</span>
      </template>
    </el-menu-item>

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

    <!-- 有多个子路由的时候 -->
    <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>
</template>

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

import { useRouter } from 'vue-router'

let $router = useRouter()

// 点击菜单的参数
const goRoute = (vc: any) => {
  $router.push(vc.index)
}
</script>

<script lang="ts">
export default {
  name: 'Menu',
}
</script>

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

找不到模块“vue-router”或其相应的类型声明

找到第一个插件,禁用掉就好了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值