Skip to content

菜单

Menu 用于显示一组操作命令或选项。支持点击、悬停、右键等多种触发方式,并提供了灵活的定位策略。

组件调用

使用 <TuiMenu> 组件包裹触发元素(如按钮)。默认情况下,它是一个右键菜单 (trigger="contextmenu"),但在常规交互中,我们常将其设为 clickhover

vue
<script setup>
import { reactive } from 'vue'

const menuItems = [
  { label: '复制', value: 'copy', icon: 'tui-icon ti-copy' },
  { label: '粘贴', value: 'paste', icon: 'tui-icon ti-paste' },
  { label: '删除', value: 'delete', icon: 'tui-icon ti-trash', divider: true },
  { label: '属性', value: 'prop', icon: 'tui-icon ti-info-circle' }
]

const handleMenuClick = (params) => {
  console.log('点击了:', params)
}
</script>

<template>
  <TuiMenu 
    trigger="click" 
    placement="bottom-start" 
    :menus="menuItems" 
    @menuClick="handleMenuClick"
  >
    <TuiButton>点击打开菜单</TuiButton>
  </TuiMenu>
</template>

指令调用

TechUI 提供了 v-tui-menu 指令,这是更轻量、更推荐的用法,可以直接挂载到任何 DOM 元素上,无需改变 DOM 结构。

vue
<template>
  <TuiButton 
    v-tui-menu="{ 
      trigger: 'hover',
      placement: 'top',
      menus: menuItems,
      menuClick: handleMenuClick 
    }"
  >
    悬停查看菜单
  </TuiButton>
</template>

触发方式

通过 trigger 属性控制菜单的激活方式:

  • click: 左键点击触发(下拉菜单)。
  • hover: 鼠标悬停触发(二级菜单或提示)。
  • contextmenu: 右键点击触发(上下文菜单)。
vue
<template>
  <div class="demo-box">
    <TuiButton v-tui-menu="{ trigger: 'click', menus: [...] }">
      点击触发
    </TuiButton>

    <TuiButton v-tui-menu="{ trigger: 'hover', menus: [...] }">
      悬停触发
    </TuiButton>

    <div 
      class="context-area"
      v-tui-menu="{ trigger: 'contextmenu', menus: [...] }"
    >
      在此区域点击右键
    </div>
  </div>
</template>

菜单项配置

菜单项数据 (menus) 支持丰富的配置,包括图标、快捷键描述、分割线以及角标(Tag/Badge)。

vue
<script setup>
const richMenus = [
  { 
    label: '新建文件', 
    value: 'new', 
    icon: 'tui-icon ti-file', 
    description: 'Ctrl+N' // 右侧快捷键提示
  },
  { 
    label: '保存', 
    value: 'save', 
    icon: 'tui-icon ti-save', 
    divider: true // 显示分割线
  },
  { 
    label: '消息通知', 
    value: 'msg', 
    icon: 'tui-icon ti-bell',
    tagContent: 8, // 显示数字角标
    tagType: 'success' // 角标颜色类型
  },
  { 
    label: '紧急任务', 
    value: 'urgent', 
    tagContent: 'Urgent', // 显示文字角标
    tagType: 'danger' 
  }
]
</script>

<template>
  <TuiMenu trigger="click" :menus="richMenus">
    <TuiButton>打开丰富菜单</TuiButton>
  </TuiMenu>
</template>

方位与定位

支持 12 个方位的精准定位,能够适应复杂的页面布局。

top, top-start, top-end, bottom, bottom-start, bottom-end, left, left-start, left-end, right, right-start, right-end

vue
<template>
  <div class="row">
    <TuiButton v-tui-menu="{ placement: 'top-start', menus: [...] }">Top Start</TuiButton>
    <TuiButton v-tui-menu="{ placement: 'top', menus: [...] }">Top</TuiButton>
    <TuiButton v-tui-menu="{ placement: 'top-end', menus: [...] }">Top End</TuiButton>
  </div>
  <div class="row">
    <TuiButton v-tui-menu="{ placement: 'right', menus: [...] }">Right</TuiButton>
  </div>
</template>

API 参考

属性名说明类型默认值
menus菜单项数据列表 (见下表)Array[]
trigger触发方式,可选 'click', 'hover', 'contextmenu'String'contextmenu'
placement弹出位置,可选 top/bottom/left/right 及其 start/end 组合String'bottom-start'
offset弹出的偏移量 (px)Number8
maxWidth菜单最大宽度 (px)Number200
zIndex菜单层级Number2000
disabled是否禁用Booleanfalse
menuClick菜单项点击的回调函数Functionnull
appendTo指定挂载的 DOM 节点选择器 (仅组件模式)String
className自定义类名String''

menus 数组中的对象结构:

属性名说明类型
label菜单项显示的文本String
value菜单项的唯一标识值 (点击回调中返回)String / Number
icon图标类名 (如 tui-icon ti-copy)String
description右侧辅助文本 (常用于快捷键提示)String
divider是否在该项下方显示分割线Boolean
tagContent角标内容 (数字或文本)String / Number
tagType角标类型 (颜色),可选 primary, success, warning, dangerString

Events

事件名说明回调参数
menuClick点击菜单项时触发(params: Object, item: Object, index: Number)

Expose

名称说明类型
show手动显示菜单() => void
hide手动隐藏菜单() => void
toggle切换显示状态() => void

全局交互监控

为了提供精准的闭合体验,TuiMenu 组件深度集成了 TechUI 的全局服务(TuiService),通过监听两个核心计数器来实现智能交互:

  • ESC 响应 (escCounter):组件实时监测全局 ESC 键的触发。当用户按下 Esc 键时,escCounter 发生变化,所有激活状态的菜单将自动关闭。
  • 智能点击检测 (clickCounter):组件监听全局点击事件。每次点击发生时,全局服务会更新 clickCounter 并传递当前的 clickTarget(点击目标元素)。组件会利用这一参数进行包含检测(Contains Check):只有当点击目标既不在菜单面板内部,也不在触发元素内部时,才会触发隐藏逻辑。这种机制确保了在复杂的嵌套 DOM 结构中,点击外部关闭(Click Outside)的逻辑依然精准无误。

定位依赖

TechUI 的气泡与弹层组件底层完全依赖于业界成熟的 Floating UI 库进行锚点定位计算。

这意味着您无需担心复杂的几何计算,组件能够自动处理以下场景:

  • 碰撞检测 (Flip):当预设位置空间不足时(如屏幕边缘),自动翻转到对面位置。
  • 视口修正 (Shift):确保气泡始终保持在视口可见范围内,不会被截断。
  • 精准偏移:通过 offset 属性实现像素级的精确定位。

您只需通过组件的 placement 属性指定期望方位,剩下的复杂计算均由底层引擎自动完成。