文章目录
- 前言
- 先看效果
- 可兼容多级菜单栏(顺便配置多少级)
- 一、新建组件
- 二、使用步骤
- 总结
- `如有启发,可点赞收藏哟~`
前言
菜单栏配置化
图标配置化参考vite动态配置svg图标及其他方式集合
先看效果
可兼容多级菜单栏(顺便配置多少级)
一、新建组件
咱分为两个组件,一个母组件menu
,还有个子组件sub-menu
(兼容多级菜单,递归使用)
- 新建
components/menu/index.vue
<script lang="ts" src="./index.ts"></script><template><el-menuclass="el-menu-demo":default-active="activeIndex":text-color="textColor":active-text-color="activeTextColor":background-color="bgColor":mode="mode":unique-opened="uniqueOpened":collapse="collapse":router="router":ellipsis="ellipsis"@select="handleSelect"><template v-for="item in menuList" :key="item + 'menu' + item.index"><SubMenu :menu="item"></SubMenu></template></el-menu>
</template>
- 新建
components/menu/index.ts
import { computed, defineComponent } from "vue";
import type { MenuType } from "@/interface/index";
import { IndexHooks } from "@/composables";
import SvgIcon from "@/components/svg-icon/index.vue";
import { translateRouteTitle } from "@/lang";
import SubMenu from "./sub-menu/index.vue";
export default defineComponent({components: {SvgIcon,SubMenu,},props: {/*** 菜单列表*/menuList: {type: Array<MenuType>,default: [{title: "菜单一",index: "0",icon: "document",subMenu: [{title: "子单一",icon: "document",index: "0-0",subMenu: [{ title: "子单2.1", icon: "document", index: "0-0-0" },{title: "子单2.1",icon: "document",index: "0-0-1",subMenu: [{ title: "子单2.1.1", icon: "document", index: "0-0-1-0" },{ title: "子单2.1.2", icon: "document", index: "0-0-1-1" },],},],},{ title: "子单二", icon: "document", index: "0-1" },],},{title: "菜单二",index: "1",icon: "document",subMenu: [{ title: "子单一", icon: "document", index: "1-0" },{ title: "子单二", icon: "document", index: "1-1" },],},{title: "菜单三",index: "2",icon: "document",},],},/*** 菜单展示模式*/mode: {type: String,default: "vertical", // horizontal - 横向 / vertical - 纵向},/*** 是否水平折叠收起菜单(仅在 mode 为 vertical 时可用)*/collapse: {type: Boolean,default: false,},/*** 是否省略多余的子项(仅在横向模式生效)*/ellipsis: {type: Boolean,default: false,},/*** 菜单的背景颜色(十六进制格式)(已被废弃,使用--bg-color)*/bgColor: {type: String,default: "#545c64",},/*** 文字颜色(十六进制格式)(已被废弃,使用--text-color)*/textColor: {type: String,default: "#fff",},/*** 活动菜单项的文本颜色(十六进制格式)(已被废弃,使用--active-color)*/activeTextColor: {type: String,default: "#ffd04b",},/*** 菜单高亮显示index*/active: {type: String,default: "0-1",},/*** 是否只保持一个子菜单的展开*/uniqueOpened: {type: Boolean,default: false,},/*** 是否启用 vue-router 模式。 启用该模式会在激活导航时以 index 作为 path 进行路由跳转 使用 default-active 来设置加载时的激活项。*/router: {type: Boolean,default: false,},},setup(props, { emit }) {const activeIndex = computed({get: () => props.active,set: (val) => {emit("update:active", val);},});const { menuList } = props;const inDepthValueOfArray = (arr: Array<MenuType>,indexs: Array<string>): Array<MenuType> | MenuType | undefined => {const index = Number(indexs[0]);if (indexs.length > 1) {const val = arr[index].subMenu;indexs.shift();return val && inDepthValueOfArray(val, indexs);} else if (indexs.length === 1) {return arr[index];} else {return arr;}};const { goTo } = IndexHooks();const handleSelect = (key: string, keyPath: string[]) => {if (!menuList) return;const indexs = key.split("-");activeIndex.value = indexs[0];const MenuType = inDepthValueOfArray(menuList, indexs);if (MenuType && !(MenuType instanceof Array)) {// goTo(MenuType?.path || "/", { t: new Date().getTime() });}};return {activeIndex,translateRouteTitle,handleSelect,};},
});
- 新建
components/menu/sub-menu/index.vue
<script lang="ts" src="./index.js"></script><template><el-sub-menu v-if="menu.subMenu" :index="menu.index"><template #title><SvgIcon v-if="menu.icon" :icon-class="menu.icon" />{{ translateRouteTitle(menu.title) }}</template><templatev-for="subItem in menu.subMenu":key="subItem + 'subItem' + menu.index"><SubMenu :menu="subItem" /></template></el-sub-menu><el-menu-item v-else :index="menu.index"><SvgIcon v-if="menu.icon" :icon-class="menu.icon" />{{ translateRouteTitle(menu.title) }}</el-menu-item>
</template>
- 新建
components/menu/sub-menu/index.ts
import { defineComponent } from "vue";
import SvgIcon from "@/components/svg-icon/index.vue";
import { translateRouteTitle } from "@/lang";
export default defineComponent({name: "SubMenu",components: {SvgIcon,},props: {menu: {type: Object,required: true,default: {title: "子单一",icon: "document",index: "0-0",subMenu: [{ title: "子单2.1", icon: "document", index: "0-0-0" },{ title: "子单2.1", icon: "document", index: "0-0-1" },],},},},setup() {return {translateRouteTitle,};},
});
二、使用步骤
咱直接以默认值做例子,具体数据可自定义,格式需以menu组件定义的,不然会报错
<script lang="ts" src="./index.ts" /><template><Menu /><!-- <Menu v-model:active="ctiHeaderMenuActive" :menuList="menuList" /> -->
</template>
import { defineComponent, reactive, ref } from "vue";
import Menu from "@/components/menu/index.vue";
export default defineComponent({components: {Menu,},setup() {return {};},
});