EpMenu
基础用法
默认纵向:
展开折叠
- Components
- Start
- EpMenu
- EpTree
- IconSelect
- Composables
- Start
- useCrud
- useDict
横向:
- Components
- Composables
插槽:
- 自定义插槽 - Components
- 自定义插槽 - Start
- 自定义插槽 - EpMenu
- 自定义插槽 - EpTree
- 自定义插槽 - IconSelect
- 自定义插槽 - Composables
- 自定义插槽 - Start
- 自定义插槽 - useCrud
- 自定义插槽 - useDict
- 自定义插槽 - Components
- 自定义插槽 - Composables
View Source
vue
<script setup lang="ts">
import type { RouteRecordRaw } from 'vue-router'
import { ref } from 'vue'
import { useRouter } from 'vitepress'
const menuList = ref<RouteRecordRaw[]>([
{
name: 'components',
path: '/components',
redirect: '',
meta: { title: 'Components', icon: 'ep:menu' },
children: [
{
name: 'components-start',
path: '/components/index',
redirect: '',
meta: { title: 'Start', icon: 'ep:menu' },
},
{
name: 'components-ep-menu',
path: '/components/ep-menu/index',
redirect: '',
meta: { title: 'EpMenu', icon: 'ep:menu' },
},
{
name: 'components-ep-tree',
path: '/components/ep-tree/index',
redirect: '',
meta: { title: 'EpTree', icon: 'ep:menu' },
},
{
name: 'components-icon-select',
path: '/components/icon-select/index',
redirect: '',
meta: { title: 'IconSelect', icon: 'ep:menu' },
},
],
},
{
name: 'composables',
path: '/composables',
redirect: '',
meta: { title: 'Composables', icon: 'ep:menu' },
children: [
{
name: 'composables-start',
path: '/composables/index',
redirect: '',
meta: { title: 'Start', icon: 'ep:menu' },
},
{
name: 'composables-use-crud',
path: '/composables/use-crud/',
redirect: '',
meta: { title: 'useCrud', icon: 'ep:menu' },
},
{
name: 'composables-use-dict',
path: '/composables/use-dict/',
redirect: '',
meta: { title: 'useDict', icon: 'ep:menu' },
},
],
},
])
const router = useRouter()
function onMenuItemClick(route: RouteRecordRaw) {
console.log('item-click', route)
if (!route.children?.length)
router.go(route.path)
}
function onMenuItemContextmenu(route: RouteRecordRaw) {
console.log('item-contextmenu', route)
}
const activeMenuIndex = ref('/components/ep-menu/index')
const collapse = ref(false)
</script>
<template>
<h3>默认纵向:</h3>
<div style="width:300px">
<el-switch v-model="collapse" active-text="折叠" inactive-text="展开" />
<EpMenu v-model="activeMenuIndex" :routes="menuList" :collapse="collapse" @item-click="onMenuItemClick" @item-contextmenu="onMenuItemContextmenu" />
</div>
<h3>横向:</h3>
<EpMenu
v-model="activeMenuIndex" :routes="menuList" mode="horizontal" @item-click="onMenuItemClick"
@item-contextmenu="onMenuItemContextmenu"
/>
<h3>插槽:</h3>
<EpMenu v-model="activeMenuIndex" :routes="menuList" :collapse="collapse">
<template #default="{ route }">
<span @click="onMenuItemClick(route)">
自定义插槽 - {{ route.meta?.title }}
</span>
</template>
</EpMenu>
<EpMenu v-model="activeMenuIndex" :routes="menuList" mode="horizontal">
<template #default="{ route }">
<div style="width:100%" @click="onMenuItemClick(route)">
自定义插槽 - {{ route.meta?.title }}
</div>
</template>
</EpMenu>
</template>
属性
名称 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
(...menuProps) | el-menu 所有属性 | MenuProps | - | - |
(...subMenuProps) | el-sub-menu 所有属性 | SubMenuProps | - | - |
v-model | 绑定的菜单项 | string | - | - |
routes | 路由 | RouteRecordRaw[] | - | - |
indexKey | 菜单索引 | string | 'name'|'path' | 'path' |
事件
名称 | 说明 | 回调参数 |
---|---|---|
item-click | menu-item 和 sub-menu 点击的回调 | (route:RouteRecordRaw) |
item-contextmenu | menu-item 和 sub-menu 右击的回调 | (route:RouteRecordRaw) |
select | 菜单激活回调 | Parameters<MenuEmits['select'] |
open | sub-menu 展开的回调 | Parameters<MenuEmits['open'] |
close | sub-menu 收起的回调 | Parameters<MenuEmits['close'] |
方法
名称 | 说明 | 参数 |
---|---|---|
open | 展开指定的 sub-menu | (index:string) |
close | 收起指定的 sub-menu | (index:string) |
插槽
名称 | 说明 | 参数 |
---|---|---|
- | 自定义菜单项内容 | {route: RouteRecordRaw} |
TIP
使用插槽需要自行处理点击事件
路由定义
ts
declare module 'vue-router' {
interface RouteMeta {
/** 菜单标题 */
title?: string
/** 菜单图标 */
icon?: string
/** 禁用菜单 */
disabled?: boolean
}
}
类型定义
ts
import type { ExtractPropTypes, PropType } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import type { MenuItemSlots } from './menu-item'
import { menuEmits as elMenuEmits, menuProps as elMenuProps } from 'element-plus'
import { omit } from 'lodash-unified'
import { menuItemProps } from './menu-item'
export const menuProps = {
...elMenuProps,
...omit(menuItemProps, 'route'),
routes: { type: Array as PropType<RouteRecordRaw[]>, default: () => [] },
modelValue: { type: String },
}
export const menuEmits = {
...elMenuEmits,
itemClick: (_route: RouteRecordRaw) => true,
itemContextmenu: (_route: RouteRecordRaw) => true,
}
export type MenuProps = ExtractPropTypes<typeof menuProps>
export type MenuEmits = typeof menuEmits
export type MenuSlots = MenuItemSlots
ts
import type { ExtractPropTypes, PropType } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import { menuProps, subMenuProps } from 'element-plus'
import { omit } from 'lodash-unified'
export const menuItemProps = {
...omit(subMenuProps, 'index'),
/** 是否折叠 */
collapse: menuProps.collapse,
/** 菜单项 */
route: { type: Object as PropType<RouteRecordRaw>, default: () => ({}) },
/** 菜单索引 */
indexKey: { type: String as PropType<'name' | 'path'>, default: 'path' },
}
export const menuItemEmits = {
click: (_route: RouteRecordRaw) => true,
contextmenu: (_route: RouteRecordRaw) => true,
}
export type MenuItemProps = ExtractPropTypes<typeof menuItemProps>
export type MenuItemEmits = typeof menuItemEmits
export interface MenuItemSlots {
default(props: { route: RouteRecordRaw }): any
}