Dropdown 下拉菜单
点击或悬停触发的操作菜单。支持子菜单与键盘导航。
基础用法
最近选择:(尚未选择)
vue
<script setup>
const options = [
{ value: 'edit', label: '编辑' },
{ value: 'copy', label: '复制' },
{ value: 'delete', label: '删除', danger: true, divided: true }
]
</script>
<template>
<SrDropdown :options="options" @select="onSelect">
<SrButton>操作</SrButton>
</SrDropdown>
</template>触发器由默认插槽提供——组件不预设外观,放按钮、放图标、放一段文字都行。
选项字段
ts
interface SrDropdownOption {
value: string | number
label: string
disabled?: boolean
danger?: boolean // 红色,用于删除这类破坏性操作
divided?: boolean // 上方加一条分隔线
shortcut?: string // 右侧的快捷键提示
children?: SrDropdownOption[] // 子菜单
}danger 与 divided 是两个独立的视觉信号:
danger用颜色强调危险性;divided用分隔线表示分组(不只是"最后一个")。
删除项通常两个都用——颜色提醒"危险",分隔线把它和常规操作隔开, 减少"手滑点到"的概率。
子菜单
children 支持一层子菜单,方向自动适应——右侧空间不够时会向左展开。
vue
const options = [
{
value: 'export',
label: '导出为',
children: [
{ value: 'export-png', label: 'PNG' },
{ value: 'export-svg', label: 'SVG' }
]
}
]子菜单方向为什么必须自适应
靠近窗口右边缘时,向右展开会被裁掉。固定方向的话, 用户永远看不到那一列——而且他也不知道有东西被裁掉了。
组件会在展开前测量可用空间,选择左或右。
触发方式
vue
<SrDropdown :options="options" trigger="click" />
<SrDropdown :options="options" trigger="hover" />触屏设备上的 hover 触发
触摸屏没有真正的悬停——hover 触发会退化成"点一下打开、 再点一下关闭",与 click 行为一致但缺少明确的视觉反馈。
触屏为主的场景建议用 click。若必须用 hover, 在 @media (hover: hover) 外保留点击兜底。
键盘导航
| 按键 | 作用 |
|---|---|
| ↓ / ↑ | 在选项间移动 |
| → | 展开子菜单 |
| ← | 收起子菜单 |
| Enter | 选中 |
| Esc | 关闭并归还焦点到触发器 |
| Home / End | 跳到首项 / 末项 |
禁用项会被跳过——焦点不会停在不可选的项上。
对齐方式
vue
<SrDropdown placement="bottom-start" />
<SrDropdown placement="bottom-end" />菜单同样会自动校正视口边缘:靠近底部时向上展开。
选中后是否关闭
closeOnSelect 默认 true。多选式菜单(点了不关、可以连续操作) 可以设为 false。
vue
<SrDropdown :options="options" :close-on-select="false" />Props
| 名称 | 类型 | 默认值 | 说明 |
|---|---|---|---|
options | SrDropdownOption[] | [] | 菜单项 |
trigger | 'click' | 'hover' | 'click' | 触发方式 |
placement | 'bottom-start' | 'bottom-end' | 'bottom-start' | 对齐方式 |
disabled | boolean | false | 是否禁用 |
closeOnSelect | boolean | true | 选中后是否关闭 |
插槽
| 名称 | 说明 |
|---|---|
default | 触发器内容 |
事件
| 事件 | 参数 | 说明 |
|---|---|---|
select | (option) | 选中某一项 |
visible-change | boolean | 显隐变化 |
无障碍
- 触发器带
aria-haspopup="menu"与aria-expanded - 菜单容器
role="menu",每项role="menuitem" danger项不能只靠颜色区分——颜色是视觉提示, 语义应由文案承担(「删除」这个词本身已说明危险)- 关闭后焦点归还触发器等,与
Modal的四要素一致(详见 Modal)