2022-06-28 vue3+ts 灵活的menu-layout简单实现

简述:

该菜单布局可以自由配置顶部菜单和侧边菜单的显示与否,也可以自由选择顶部菜单和侧边菜单的父子关系,此菜单布局相较mx-design中的menu-layout父子菜单关系相对灵活,且可以在一个工程中多次使用,通过路由来控制,使用该菜单布局的页面需要创建一个根路由,component引入该菜单组件。
示例

{
    path: '/',
    name: 'MChain',
    component: () => import('@/layout/MChain-menu-layout.vue'),
    redirect: '/MBoundaryApp',
    meta: {...}
    children:[...]
}

配置项说明

meta:

hideChildrenInMenu:true | false 是否隐藏子菜单(所谓子菜单见下图红框),如果不设置则默认展示子菜单
1656398797782.png
icon:菜单图标,图标用法mx-design框架中有提及,这里主要说明的是:以 http://cp.oss.pcep.cnpc.com.cn/mx-icon 为开头的图标无法通过css改变其样式(比如颜色),可以直接把图标svg下载,放到assets>icons文件夹下,在meta中直接使用 icon: self-图标名即可。如果不想显示图标就不配置
1656399090071.png

1656399132288.png
topMenuStep:顶部菜单对应的子路由层级,如果设置为0或不设置则表示没有顶部菜单
siderMenuStep:侧边菜单对应的子路由层级,如果设置为0或不设置则表示没有侧边菜单
示例1:顶部菜单做父菜单,侧边菜单做子菜单(或者说1级子路由做顶部菜单,2级子路由做侧边菜单)
export const customPageRouter: RouteRecordRaw[] = [
  // 自定义的菜单布局页面
  {
    path: '/',
    name: 'MChain',
    component: () => import('@/layout/MChain-menu-layout.vue'),
    redirect: '/MBoundaryApp',
    meta: {
      title: '梦链工作台',
      topMenuStep:1,// 想要将第几级子菜单作为顶部菜单,如果设置为0或不设置则表示没有相应菜单
      siderMenuStep: 2 // 想要将第几级子菜单作为侧边菜单,示例:/MBoundaryApp 是1级子菜单,/MBoundaryApp/subject是2级子菜单
    },
    children: [
      {
        path: '/MBoundaryApp',
        name: 'MBoundaryApp',   
        redirect: '/MBoundaryApp/subject',    //如果想默认选中该子菜单,需要这句重定向 
        component: () => import('@/views/MBoundaryApp/index.vue'),
        meta: {
          title: '梦境认知环境',
          hideChildrenInMenu:true //是否在自身中隐藏子菜单,如果不设置则默认显示
        },
        children: [
          {
            path: '/MBoundaryApp/subject',
            name: 'subject',
            component: () => import('@/views/MBoundaryApp/subject.vue'),
            meta: {
              title: '学科模块',
              icon: 'self-epai-fa-pzgl',
            },            
          },
          {
            path: '/MBoundaryApp/myProject',
            name: 'myProject',
            component: () => import('@/views/MBoundaryApp/myProjects.vue'),
            meta: {
              title: '我的项目',
              icon: 'self-xiangmuguanli'
            }
          },
          
          {
            path: '/MBoundaryApp/myOperation',
            name: 'myOperation',
            component: () => import('@/views/MBoundaryApp/myOperation.vue'),
            meta: {
              title: '我的运营',
              icon: 'self-xiangmuguanli'
            }
          },
          {
            path: '/MBoundaryApp/myInfo',
            name: 'myInfo',
            component: () => import('@/views/MBoundaryApp/myInfo.vue'),
            meta: {
              title: '个人信息',
              icon: 'self-user-info'
            }
          }
        ]
      },
      {
        path: '/MEcoApp',
        name: 'MEcoApp',
        component: () => import('@/views/MEcoApp/index.vue'),
        meta: {
          title: '梦赢开发平台'
        }
      },
      {
        path: '/test',
        name: 'test',
        component: () => import('@/views/test/index.vue'),
        meta: {
          title: 'test'
        }
      },
      {
        path: '/testa',
        name: 'testa',
        component: () => import('@/views/test/testa.vue'),
        meta: {
          title: 'testa'
        }
      },
      {
        path: '/subject-module',
        name: 'subjectModule',
        component: () => import('@/views/subjectModule/index.vue'),
        meta: {
          title: 'subjectModule'
        }
      }
    ]
  }  
]
显示效果
1656399964139.png
示例2:侧边菜单做父菜单,顶部菜单做子菜单

将示例1中的topMenuStep和siderMenuStep交换值即可

显示效果
1656400437631.png
示例3:一级子路由做顶部菜单,三级子路由做侧边菜单,路由中需要重定向,以确保可以默认访问到三级子路由
export const customPageRouter: RouteRecordRaw[] = [
  // 自定义的菜单布局页面
  {
    path: '/',
    name: 'MChain',
    component: () => import('@/layout/MChain-menu-layout.vue'),
    redirect: '/MBoundaryApp',
    meta: {
      title: '梦链工作台',
      topMenuStep:1,// 想要将第几级子菜单作为顶部菜单,如果设置为0或不设置则表示没有相应菜单
      siderMenuStep: 3 // 想要将第几级子菜单作为侧边菜单,示例:/MBoundaryApp 是1级子菜单,/MBoundaryApp/subject是2级子菜单
    },
    children: [
      {
        path: '/MBoundaryApp',
        name: 'MBoundaryApp',   
        redirect: '/MBoundaryApp/subject',  
        component: () => import('@/views/MBoundaryApp/index.vue'),
        meta: {
          title: '梦境认知环境',
          hideChildrenInMenu:true //是否在自身中隐藏子菜单,如果不设置则默认显示
        },
        children: [
          {
            path: '/MBoundaryApp/subject',
            name: 'subject',
            redirect:'/MBoundaryApp/subject/test',//如果顶部菜单和侧边菜单是父孙或更远的关系,那么默认需要加上重定向,用来默认展示孙子菜单
            component: () => import('@/views/MBoundaryApp/subject.vue'),
            meta: {
              title: '学科模块',
              icon: 'self-epai-fa-pzgl',
            },  
            children:[
              {
                path: '/MBoundaryApp/subject/test',
                name: 'subject-test',
                component: () => import('@/views/test/index.vue'),
                meta: {
                  title: 'test'
                }
              },
            ]          
          },
          {
            path: '/MBoundaryApp/myProject',
            name: 'myProject',
            component: () => import('@/views/MBoundaryApp/myProjects.vue'),
            meta: {
              title: '我的项目',
              icon: 'self-xiangmuguanli'
            }
          },
          
          {
            path: '/MBoundaryApp/myOperation',
            name: 'myOperation',
            component: () => import('@/views/MBoundaryApp/myOperation.vue'),
            meta: {
              title: '我的运营',
              icon: 'self-xiangmuguanli'
            }
          },
          {
            path: '/MBoundaryApp/myInfo',
            name: 'myInfo',
            component: () => import('@/views/MBoundaryApp/myInfo.vue'),
            meta: {
              title: '个人信息',
              icon: 'self-user-info'
            }
          }
        ]
      },
      {
        path: '/MEcoApp',
        name: 'MEcoApp',
        component: () => import('@/views/MEcoApp/index.vue'),
        meta: {
          title: '梦赢开发平台'
        }
      },
      {
        path: '/test',
        name: 'test',
        component: () => import('@/views/test/index.vue'),
        meta: {
          title: 'test'
        }
      },
      {
        path: '/testa',
        name: 'testa',
        component: () => import('@/views/test/testa.vue'),
        meta: {
          title: 'testa'
        }
      },
      {
        path: '/subject-module',
        name: 'subjectModule',
        component: () => import('@/views/subjectModule/index.vue'),
        meta: {
          title: 'subjectModule'
        }
      }
    ]
  }
]
显示效果
1656400873988.png
示例4:1级路由做顶部菜单,2级路由做侧边菜单,同时侧边菜单要展示子菜单,这种情况需要搭配路由重定向,以确定默认选中的最末级子菜单
export const customPageRouter: RouteRecordRaw[] = [
  // 自定义的菜单布局页面
  {
    path: '/',
    name: 'MChain',
    component: () => import('@/layout/MChain-menu-layout.vue'),
    redirect: '/MBoundaryApp',
    meta: {
      title: '梦链工作台',
      topMenuStep:1,// 想要将第几级子菜单作为顶部菜单,如果设置为0或不设置则表示没有相应菜单
      siderMenuStep: 2 // 想要将第几级子菜单作为侧边菜单,示例:/MBoundaryApp 是1级子菜单,/MBoundaryApp/subject是2级子菜单
    },
    children: [
      {
        path: '/MBoundaryApp',
        name: 'MBoundaryApp',   
        redirect: '/MBoundaryApp/subject',  
        component: () => import('@/views/MBoundaryApp/index.vue'),
        meta: {
          title: '梦境认知环境',
          hideChildrenInMenu:true //是否在自身中隐藏子菜单,如果不设置则默认显示
        },
        children: [
          {
            path: '/MBoundaryApp/subject',
            name: 'subject',
            redirect:'/MBoundaryApp/subject/myProject',
            component: () => import('@/views/MBoundaryApp/subject.vue'),
            meta: {
              title: '学科模块',
              icon: 'self-epai-fa-pzgl',
            }, 
            children:[
              {
                path: '/MBoundaryApp/subject/myProject',
                name: 'subject-myProject',
                component: () => import('@/views/MBoundaryApp/myProjects.vue'),
                meta: {
                  title: '我的项目',
                  icon: 'self-xiangmuguanli'
                }
              },
            ]               
          },
          {
            path: '/MBoundaryApp/myProject',
            name: 'myProject',
            component: () => import('@/views/MBoundaryApp/myProjects.vue'),
            meta: {
              title: '我的项目',
              icon: 'self-xiangmuguanli'
            }
          },
          
          {
            path: '/MBoundaryApp/myOperation',
            name: 'myOperation',
            component: () => import('@/views/MBoundaryApp/myOperation.vue'),
            meta: {
              title: '我的运营',
              icon: 'self-xiangmuguanli'
            }
          },
          {
            path: '/MBoundaryApp/myInfo',
            name: 'myInfo',
            component: () => import('@/views/MBoundaryApp/myInfo.vue'),
            meta: {
              title: '个人信息',
              icon: 'self-user-info'
            }
          }
        ]
      },
      {
        path: '/MEcoApp',
        name: 'MEcoApp',
        component: () => import('@/views/MEcoApp/index.vue'),
        meta: {
          title: '梦赢开发平台'
        }
      },
      {
        path: '/test',
        name: 'test',
        component: () => import('@/views/test/index.vue'),
        meta: {
          title: 'test'
        }
      },
      {
        path: '/testa',
        name: 'testa',
        component: () => import('@/views/test/testa.vue'),
        meta: {
          title: 'testa'
        }
      },
      {
        path: '/subject-module',
        name: 'subjectModule',
        component: () => import('@/views/subjectModule/index.vue'),
        meta: {
          title: 'subjectModule'
        }
      }
    ]
  }
]
显示效果
image.png

注:topMenuStep 和 siderMenuStep的值可以相等,但是实际业务中基本不会有这种需求,所以不建议大家使用

你可能感兴趣的:(2022-06-28 vue3+ts 灵活的menu-layout简单实现)