vue-封装菜单组件

举报
林太白 发表于 2025/01/27 19:16:00 2025/01/27
【摘要】 vue封装菜单组件

封装菜单组件

1、概述

在项目之中,一般我们的后台管理正常结构部分都是包括菜单部分,左侧菜单是必不可少的,菜单部分一般由以下几个部分组成

  • 菜单标题
  • 菜单图标
  • 菜单子项
  • 菜单折叠

我们可以简单的预览一下正常一个完整的后台管理的大致页面应该是什么样子:

2、结构搭建

接下来我们就在 vue3 之中搭建一个左侧的菜单组件,然后进行封装,在我们的项目之中我们选择的是国内目前最为流行的 ui 框架,element-plus,接下来我们就围绕他的左侧折叠面板和菜单进行开发和封装我们的菜单组件。

可以看出,菜单栏大致分为两类,一类是有子菜单的,一类是无子菜单的。我们可以对这两类进行分类,然后根据路由列表,动态渲染菜单栏。

之前我们搭建好了一个基础的 vue3 项目,并且引入了 element-plus,接下来我们就开始引入我们的菜单组件代码,这部分直接使用官方的就行。

<template>
  <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
    <el-radio-button :value="false">expand</el-radio-button>
    <el-radio-button :value="true">collapse</el-radio-button>
  </el-radio-group>
  <el-menu
    default-active="2"
    class="el-menu-vertical-demo"
    :collapse="isCollapse"
    @open="handleOpen"
    @close="handleClose"
  >
    <el-sub-menu index="1">
      <template #title>
        <el-icon><location /></el-icon>
        <span>Navigator One</span>
      </template>
      <el-menu-item-group>
        <template #title><span>Group One</span></template>
        <el-menu-item index="1-1">item one</el-menu-item>
        <el-menu-item index="1-2">item two</el-menu-item>
      </el-menu-item-group>
      <el-menu-item-group title="Group Two">
        <el-menu-item index="1-3">item three</el-menu-item>
      </el-menu-item-group>
      <el-sub-menu index="1-4">
        <template #title><span>item four</span></template>
        <el-menu-item index="1-4-1">item one</el-menu-item>
      </el-sub-menu>
    </el-sub-menu>
    <el-menu-item index="2">
      <el-icon><icon-menu /></el-icon>
      <template #title>Navigator Two</template>
    </el-menu-item>
    <el-menu-item index="3" disabled>
      <el-icon><document /></el-icon>
      <template #title>Navigator Three</template>
    </el-menu-item>
    <el-menu-item index="4">
      <el-icon><setting /></el-icon>
      <template #title>Navigator Four</template>
    </el-menu-item>
  </el-menu>
</template>

<script lang="ts" setup>
import { ref } from "vue";
import {
  Document,
  Menu as IconMenu,
  Location,
  Setting,
} from "@element-plus/icons-vue";

const isCollapse = ref(true);
const handleOpen = (key: string, keyPath: string[]) => {
  console.log(key, keyPath);
};
const handleClose = (key: string, keyPath: string[]) => {
  console.log(key, keyPath);
};
</script>

<style>
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
  min-height: 400px;
}
</style>

然后我们看看引入官方默认提供给我们菜单的效果

3、菜单渲染

接下来我们就把我们后台管理部分的所有菜单全部导入进来,然后对菜单实施一个渲染,然后我们就可以看到完整的菜单结构了。

☞ 在 router=> index 之中先把我们的 admin(后台管理部分)的菜单隔离出来

这里隔离出来也是为了方便我自己的操作

// 后台部分相关路由
export const adminRouter= [
    {
      path: '/user', // 用户页面
      name: 'user',
      component: () => import('@/views/admin/user/index.vue'),
    },
];

//使用amdin部分路由的时候
// 默认路由 home页面
 {
    path: '/admin',
    name: 'admin',
    component: () => import('@/views/admin/index.vue'),
    children:[...adminRouter],
},

☞ 然后在我们的后台菜单里面去拿这部分菜单的值,在组件 Menu=> leftMenu 部分封装我们这部分 admin 的值

  • leftMenu 里面输出查看
import { adminRouter } from "@/router";
console.log(adminRouter, "adminRouter");

☞ 查看输出的值,可以看到,这个时候我们已经拿到了我们需要的菜单,接下来就可以完善菜单了

[
  {
    path: "/user",
    name: "user",
  },
];

☞ 渲染第一层菜单

菜单首先需要一个标题,接下来我们完善菜单,然后渲染第一层的菜单

// 后台部分相关路由
export const adminRouter = [
  {
    path: '/home', // 后台主页
    name: 'home',
    component: () => import('@/views/admin/adminhome/index.vue'),
    meta: { title: '后台主页' },
  },
  {
    path: '/system', // 系统管理
    name: 'system',
    component: () => import('@/views/admin/user/index.vue'),
    meta: { title: '系统管理' },
    children: [
      {
        path: '/role', // 角色管理
        name: 'role',
        component: () => import('@/views/admin/role/index.vue'),
      },
      {
        path: '/user', // 用户管理
        name: 'user',
        component: () => import('@/views/admin/user/index.vue'),
      },
    ],
  },
];

在菜单使用部分进行渲染

<el-menu
  default-active="1"
  class="el-menu-vertical-demo"
  :collapse="isCollapse"
  @open="handleOpen"
  @close="handleClose"
>
  <el-menu-item :index="index" v-for="(val,index) in adminRouter" :key="index">
    <el-icon><icon-menu /></el-icon>
    <template #title>{{val.meta?.title}}</template>
  </el-menu-item>
</el-menu>

查看效果,这个时候我们的第一层菜单已经封装好了

4、子菜单封装

我们封装好了第一层的菜单以后还不够,因为可能菜单的层级会有无数个,这个时候我们就需要把菜单写成嵌套组件

☞ src=> layout => leftAside => SideItem.vue

这里我们直接将我们之前的部分挪移过来进行一些简单的封装

<template>
	<el-menu-item :index="sideItemdata.path"  v-if="!sideItemdata.children || sideItemdata.children.length === 0">
      <el-icon><Menu /></el-icon>
      <template #title>{{ sideItemdata.meta.title?sideItemdata.meta.title:'--' }}</template>
    </el-menu-item>
 	<el-sub-menu :index="sideItemdata.path" v-else>
 		<template #title>
            <el-icon><Operation /></el-icon>
            <span>{{ sideItemdata.meta.title?sideItemdata.meta.title:'--' }}</span>
        </template>
        <SideItem v-for="(item,index) in sideItemdata.children" :key="item.path + index" :sideItemdata="item"/>
    </el-sub-menu> 
</template>
<script setup>
import SideItem from './SideItem.vue'
const props = defineProps({
    sideItemdata: {
        type: Object,
        required: true
    },
    isNest: {
        type: Boolean,
        default: false
    },
    basePath: {
        type: String,
        default: ''
    }
})
</script>

☞ src=> layout => leftAside => index.vue

更换一下我们之前的组件主要的部分,父组件引入使用子组件

<el-menu background-color="#FFF" text-color="#030303" active-text-color="#1890FF" default-active="1" class="el-menu-vertical-demo" :collapse="isCollapse" @open="handleOpen" @close="handleClose">
        <SideItem v-for="(item,index) in sideRouters" :key="item.path + index" :sideItemdata="item"/>
</el-menu>

import SideItem from './SideItem.vue'

查看我们的效果

5、菜单事件完善

接下来我们完善一下菜单子组件的点击事件

这里我是直接添加到el-menu-item 上的 

@click="topageUrl(sideItemdata)"

//引入路由
import {useRouter} from 'vue-router' 

//使用 
const router=useRouter();

//跳转
const topageUrl=(row)=>{
	  router.push(row);
}

6、菜单样式属性

el-menu上的属性显示

background-color="#FFF"  // 设置默认背景色
text-color="#030303" // 设置默认文字颜色
active-text-color="#1890FF" // 设置点击后文字颜色
default-active="1" // 设置默认选中
class="el-menu-vertical-demo" // 设置样式
:collapse="isCollapse" // 设置折叠
@open="handleOpen" // 设置展开
@close="handleClose" // 设置关闭

7、菜单过滤

在我们正常的菜单显示过程中,很多时候我们的菜单并不需要展示出来,这个时候我们菜单之中有个属性hidden来进行控制显示隐藏

  • 路由信息配置
{
    path: '/userinfo', // 用户页面
    name: 'userinfo',
    meta: { title: '用户信息', icon: '<User/>' },
    children: [],
    hidden:false, // 隐藏
    component: () => import('@/pages/userInfo.vue'),
},

  • 在菜单之中我们过滤一下
onMounted(() => {
  console.log(router.options.routes, '路由--all');
  router.options.routes.forEach((item) => {
      // console.log(item);
      if (item.name == '/') {
          sideRouters.value = item.children.filter((row)=>!row.hidden);
      }
  })
})
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。