Skip to content

Menu 导航菜单

为页面和功能提供导航的菜单列表。

何时使用

导航菜单是一个网站的灵魂,用户依赖导航在各个页面中进行跳转。一般分为顶部导航和侧边导航,顶部导航提供全局性的类目和功能,侧边导航提供多级结构来收纳和排列网站架构。

更多布局和导航的使用可以参考:通用布局

顶部导航

水平的顶部导航菜单。

vue
<template>
  <g-menu v-model:selectedKeys="current" mode="horizontal">
    <g-menu-item key="mail">
      <template #icon>
        <g-icon type="mail" />
      </template>
      Navigation One
    </g-menu-item>
    <g-menu-item key="app" disabled>
      <template #icon>
        <g-icon type="appstore" />
      </template>
      Navigation Two
    </g-menu-item>
    <g-sub-menu key="SubMenu">
      <template #title>
        <span>
          <g-icon type="setting" />
          Navigation Three - Submenu
        </span>
      </template>
      <g-menu-item-group title="Item 1">
        <g-menu-item key="setting:1">Option 1</g-menu-item>
        <g-menu-item key="setting:2">Option 2</g-menu-item>
      </g-menu-item-group>
      <g-menu-item-group title="Item 2">
        <g-menu-item key="setting:3">Option 3</g-menu-item>
        <g-menu-item key="setting:4">Option 4</g-menu-item>
      </g-menu-item-group>
    </g-sub-menu>
    <g-menu-item key="alipay">
      <a href="https://ant.design" target="_blank" rel="noopener noreferrer">
        Navigation Four - Link
      </a>
    </g-menu-item>
  </g-menu>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const current = ref(['mail'])
    
    return {
      current
    }
  }
}
</script>

内嵌菜单

垂直菜单,子菜单内嵌在菜单区域。

vue
<template>
  <g-menu
    v-model:selectedKeys="selectedKeys"
    v-model:openKeys="openKeys"
    mode="inline"
    theme="dark"
    :inline-collapsed="collapsed"
    style="width: 256px;"
  >
    <g-menu-item key="1">
      <template #icon>
        <g-icon type="pie-chart" />
      </template>
      <span>Option 1</span>
    </g-menu-item>
    <g-menu-item key="2">
      <template #icon>
        <g-icon type="desktop" />
      </template>
      <span>Option 2</span>
    </g-menu-item>
    <g-menu-item key="3">
      <template #icon>
        <g-icon type="inbox" />
      </template>
      <span>Option 3</span>
    </g-menu-item>
    <g-sub-menu key="sub1">
      <template #title>
        <span>
          <g-icon type="mail" />
          <span>Navigation One</span>
        </span>
      </template>
      <g-menu-item key="5">Option 5</g-menu-item>
      <g-menu-item key="6">Option 6</g-menu-item>
      <g-menu-item key="7">Option 7</g-menu-item>
      <g-menu-item key="8">Option 8</g-menu-item>
    </g-sub-menu>
    <g-sub-menu key="sub2">
      <template #title>
        <span>
          <g-icon type="appstore" />
          <span>Navigation Two</span>
        </span>
      </template>
      <g-menu-item key="9">Option 9</g-menu-item>
      <g-menu-item key="10">Option 10</g-menu-item>
      <g-sub-menu key="sub3" title="Submenu">
        <g-menu-item key="11">Option 11</g-menu-item>
        <g-menu-item key="12">Option 12</g-menu-item>
      </g-sub-menu>
    </g-sub-menu>
  </g-menu>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const collapsed = ref(false)
    const selectedKeys = ref(['1'])
    const openKeys = ref(['sub1'])
    
    return {
      collapsed,
      selectedKeys,
      openKeys
    }
  }
}
</script>

缩起内嵌菜单

内嵌菜单可以被缩起/展开。

你可以在 Layout 里查看侧边布局结合的完整示例。

vue
<template>
  <div style="width: 256px;">
    <g-button type="primary" @click="toggleCollapsed" style="margin-bottom: 16px;">
      <g-icon :type="collapsed ? 'menu-unfold' : 'menu-fold'" />
    </g-button>
    <g-menu
      v-model:selectedKeys="selectedKeys"
      v-model:openKeys="openKeys"
      mode="inline"
      theme="dark"
      :inline-collapsed="collapsed"
    >
      <g-menu-item key="1">
        <template #icon>
          <g-icon type="pie-chart" />
        </template>
        <span>Option 1</span>
      </g-menu-item>
      <g-menu-item key="2">
        <template #icon>
          <g-icon type="desktop" />
        </template>
        <span>Option 2</span>
      </g-menu-item>
      <g-menu-item key="3">
        <template #icon>
          <g-icon type="inbox" />
        </template>
        <span>Option 3</span>
      </g-menu-item>
      <g-sub-menu key="sub1">
        <template #title>
          <span>
            <g-icon type="mail" />
            <span>Navigation One</span>
          </span>
        </template>
        <g-menu-item key="5">Option 5</g-menu-item>
        <g-menu-item key="6">Option 6</g-menu-item>
        <g-menu-item key="7">Option 7</g-menu-item>
        <g-menu-item key="8">Option 8</g-menu-item>
      </g-sub-menu>
      <g-sub-menu key="sub2">
        <template #title>
          <span>
            <g-icon type="appstore" />
            <span>Navigation Two</span>
          </span>
        </template>
        <g-menu-item key="9">Option 9</g-menu-item>
        <g-menu-item key="10">Option 10</g-menu-item>
        <g-sub-menu key="sub3" title="Submenu">
          <g-menu-item key="11">Option 11</g-menu-item>
          <g-menu-item key="12">Option 12</g-menu-item>
        </g-sub-menu>
      </g-sub-menu>
    </g-menu>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const collapsed = ref(false)
    const selectedKeys = ref(['1'])
    const openKeys = ref(['sub1'])
    
    const toggleCollapsed = () => {
      collapsed.value = !collapsed.value
    }
    
    return {
      collapsed,
      selectedKeys,
      openKeys,
      toggleCollapsed
    }
  }
}
</script>

只展开当前父级菜单

点击菜单,收起其他展开的所有菜单,保持菜单聚焦简洁。

vue
<template>
  <g-menu
    v-model:selectedKeys="selectedKeys"
    v-model:openKeys="openKeys"
    mode="inline"
    style="width: 256px;"
    @openChange="onOpenChange"
  >
    <g-sub-menu key="sub1">
      <template #title>
        <span>
          <g-icon type="mail" />
          <span>Navigation One</span>
        </span>
      </template>
      <g-menu-item key="1">Option 1</g-menu-item>
      <g-menu-item key="2">Option 2</g-menu-item>
      <g-menu-item key="3">Option 3</g-menu-item>
      <g-menu-item key="4">Option 4</g-menu-item>
    </g-sub-menu>
    <g-sub-menu key="sub2">
      <template #title>
        <span>
          <g-icon type="appstore" />
          <span>Navigation Two</span>
        </span>
      </template>
      <g-menu-item key="5">Option 5</g-menu-item>
      <g-menu-item key="6">Option 6</g-menu-item>
      <g-sub-menu key="sub3" title="Submenu">
        <g-menu-item key="7">Option 7</g-menu-item>
        <g-menu-item key="8">Option 8</g-menu-item>
      </g-sub-menu>
    </g-sub-menu>
    <g-sub-menu key="sub4">
      <template #title>
        <span>
          <g-icon type="setting" />
          <span>Navigation Three</span>
        </span>
      </template>
      <g-menu-item key="9">Option 9</g-menu-item>
      <g-menu-item key="10">Option 10</g-menu-item>
      <g-menu-item key="11">Option 11</g-menu-item>
      <g-menu-item key="12">Option 12</g-menu-item>
    </g-sub-menu>
  </g-menu>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const selectedKeys = ref(['1'])
    const openKeys = ref(['sub1'])
    const rootSubmenuKeys = ['sub1', 'sub2', 'sub4']
    
    const onOpenChange = (keys) => {
      const latestOpenKey = keys.find(key => openKeys.value.indexOf(key) === -1)
      if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
        openKeys.value = keys
      } else {
        openKeys.value = latestOpenKey ? [latestOpenKey] : []
      }
    }
    
    return {
      selectedKeys,
      openKeys,
      onOpenChange
    }
  }
}
</script>

垂直菜单

子菜单是弹出的形式。

vue
<template>
  <g-menu
    v-model:selectedKeys="selectedKeys"
    mode="vertical"
    style="width: 256px;"
  >
    <g-menu-item key="1">
      <template #icon>
        <g-icon type="pie-chart" />
      </template>
      Option 1
    </g-menu-item>
    <g-menu-item key="2">
      <template #icon>
        <g-icon type="desktop" />
      </template>
      Option 2
    </g-menu-item>
    <g-menu-item key="3">
      <template #icon>
        <g-icon type="inbox" />
      </template>
      Option 3
    </g-menu-item>
    <g-sub-menu key="sub1">
      <template #title>
        <span>
          <g-icon type="mail" />
          <span>Navigation One</span>
        </span>
      </template>
      <g-menu-item-group title="Item 1">
        <g-menu-item key="5">Option 5</g-menu-item>
        <g-menu-item key="6">Option 6</g-menu-item>
      </g-menu-item-group>
      <g-menu-item-group title="Item 2">
        <g-menu-item key="7">Option 7</g-menu-item>
        <g-menu-item key="8">Option 8</g-menu-item>
      </g-menu-item-group>
    </g-sub-menu>
    <g-sub-menu key="sub2">
      <template #title>
        <span>
          <g-icon type="appstore" />
          <span>Navigation Two</span>
        </span>
      </template>
      <g-menu-item key="9">Option 9</g-menu-item>
      <g-menu-item key="10">Option 10</g-menu-item>
      <g-sub-menu key="sub3" title="Submenu">
        <g-menu-item key="11">Option 11</g-menu-item>
        <g-menu-item key="12">Option 12</g-menu-item>
      </g-sub-menu>
    </g-sub-menu>
  </g-menu>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const selectedKeys = ref(['1'])
    
    return {
      selectedKeys
    }
  }
}
</script>

主题

内建了两套主题 light|dark,默认 light

vue
<template>
  <div>
    <g-switch
      v-model:checked="theme"
      checked-children="Dark"
      un-checked-children="Light"
    />
    <br />
    <br />
    <g-menu
      v-model:selectedKeys="current"
      :theme="theme ? 'dark' : 'light'"
      mode="horizontal"
    >
      <g-menu-item key="mail">
        <template #icon>
          <g-icon type="mail" />
        </template>
        Navigation One
      </g-menu-item>
      <g-menu-item key="app" disabled>
        <template #icon>
          <g-icon type="appstore" />
        </template>
        Navigation Two
      </g-menu-item>
      <g-sub-menu key="SubMenu">
        <template #title>
          <span>
            <g-icon type="setting" />
            Navigation Three - Submenu
          </span>
        </template>
        <g-menu-item-group title="Item 1">
          <g-menu-item key="setting:1">Option 1</g-menu-item>
          <g-menu-item key="setting:2">Option 2</g-menu-item>
        </g-menu-item-group>
        <g-menu-item-group title="Item 2">
          <g-menu-item key="setting:3">Option 3</g-menu-item>
          <g-menu-item key="setting:4">Option 4</g-menu-item>
        </g-menu-item-group>
      </g-sub-menu>
      <g-menu-item key="alipay">
        <a href="https://ant.design" target="_blank" rel="noopener noreferrer">
          Navigation Four - Link
        </a>
      </g-menu-item>
    </g-menu>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const current = ref(['mail'])
    const theme = ref(false)
    
    return {
      current,
      theme
    }
  }
}
</script>

API

参数说明类型默认值版本
defaultOpenKeys初始展开的 SubMenu 菜单项 key 数组string[]-
defaultSelectedKeys初始选中的菜单项 key 数组string[]-
expandIcon自定义展开图标slot | (props: {isOpen, record}) => VNode-4.0.0
forceSubMenuRender在子菜单展示之前就渲染进 DOMbooleanfalse
inlineCollapsedinline 时菜单是否收起状态boolean-
inlineIndentinline 模式的菜单缩进宽度number24
mode菜单类型,现在支持垂直、水平、和内嵌模式三种vertical | horizontal | inlinevertical
multiple是否允许多选booleanfalse
openKeys(v-model)当前展开的 SubMenu 菜单项 key 数组string[]-
overflowedIndicator自定义 Menu 折叠时的图标slot<EllipsisOutlined />
selectable是否允许选中booleantrue
selectedKeys(v-model)当前选中的菜单项 key 数组string[]-
subMenuCloseDelay用户鼠标离开子菜单后关闭延时,单位:秒number0.1
subMenuOpenDelay用户鼠标进入子菜单后开启延时,单位:秒number0
theme主题颜色light | darklight
triggerSubMenuActionSubMenu 展开/关闭的触发行为hover | clickhover
事件名称说明回调参数
click点击 MenuItem 调用此函数function({ item, key, keyPath, domEvent })
deselect取消选中时调用,仅在 multiple 生效function({ item, key, selectedKeys })
openChangeSubMenu 展开/关闭的回调function(openKeys: string[])
select被选中时调用function({ item, key, selectedKeys })
参数说明类型默认值版本
disabled是否禁用booleanfalse
keyitem 的唯一标志string-
title设置收缩时展示的悬浮标题string-
参数说明类型默认值版本
disabled是否禁用booleanfalse
key唯一标志string-
popupClassName子菜单样式,mode="inline" 时无效string-
popupOffset子菜单偏移量,mode="inline" 时无效[number, number]-
title子菜单项值string | slot-
参数说明类型默认值版本
title分组标题string | slot-

菜单项分割线,只用在弹出菜单内。

更多属性请参考 Tooltip。

Released under the MIT License.