Skip to content

Dropdown 下拉菜单

将动作或菜单折叠到下拉菜单中。

基础用法

通过组件 slot 来设置下拉触发的元素以及需要通过具名 slot 为 dropdown 来设置下拉菜单。

通过 slot 传入 item
通过 props 传入 item

<script setup lang="ts">
	import { type DropdownItemProps } from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]
</script>

<template>
	<div class="row">
		<div class="col">
			<div class="desc">通过 slot 传入 item</div>
			<vr-dropdown>
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
				<template #dropdown>
					<vr-dropdown-item command="1">Action 1</vr-dropdown-item>
					<vr-dropdown-item command="2" label="Action 2" />
					<vr-dropdown-item command="3" disabled>Action 3</vr-dropdown-item>
					<vr-dropdown-item command="4" divided>Action 4</vr-dropdown-item>
				</template>
			</vr-dropdown>
		</div>
		<div class="col">
			<div class="desc">通过 props 传入 item</div>
			<vr-dropdown :items="items">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
	</div>
</template>

<style scoped>
	.row {
		display: flex;
		flex-wrap: wrap;
	}
	.col {
		flex: 1;
	}
	.desc {
		display: block;
		color: var(--vr-text-color-secondary);
		font-size: 14px;
		margin-bottom: 20px;
	}
	.dropdown-link {
		display: flex;
		align-items: center;
		cursor: pointer;
		color: var(--vr-color-primary);
		i {
			margin-left: 8px;
		}
	}
</style>

触发方式

通过设置 trigger 属性来改变触发方式。

hover to trigger
click to trigger
right click to trigger

<script setup lang="ts">
	import { type DropdownItemProps } from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]
</script>

<template>
	<div class="row">
		<div class="col">
			<div class="desc">hover to trigger</div>
			<vr-dropdown :items="items">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
		<div class="col">
			<div class="desc">click to trigger</div>
			<vr-dropdown :items="items" trigger="click">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
		<div class="col">
			<div class="desc">right click to trigger</div>
			<vr-dropdown :items="items" trigger="contextmenu">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
	</div>
</template>

<style scoped>
	.row {
		display: flex;
		flex-wrap: wrap;
	}
	.col {
		flex: 1;
	}
	.desc {
		display: block;
		color: var(--vr-text-color-secondary);
		font-size: 14px;
		margin-bottom: 20px;
	}
	.dropdown-link {
		display: flex;
		align-items: center;
		cursor: pointer;
		color: var(--vr-color-primary);
		i {
			margin-left: 8px;
		}
	}
</style>

点击菜单隐藏

可以通过 hide-on-click 属性来配置。 下拉菜单默认在点击菜单项后会被隐藏,将 hide-on-click 属性设置为 false 可以关闭此功能。

hide-on-click="true"(default)
hide-on-click="false"

<script setup lang="ts">
	import { type DropdownItemProps } from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]
</script>

<template>
	<div class="row">
		<div class="col">
			<div class="desc">hide-on-click="true"(default)</div>
			<vr-dropdown :items="items">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
		<div class="col">
			<div class="desc">hide-on-click="false"</div>
			<vr-dropdown :items="items" :hide-on-click="false">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
	</div>
</template>

<style scoped>
	.row {
		display: flex;
		flex-wrap: wrap;
	}
	.col {
		flex: 1;
	}
	.desc {
		display: block;
		color: var(--vr-text-color-secondary);
		font-size: 14px;
		margin-bottom: 20px;
	}
	.dropdown-link {
		display: flex;
		align-items: center;
		cursor: pointer;
		color: var(--vr-color-primary);
		i {
			margin-left: 8px;
		}
	}
</style>

指令事件

点击菜单项后会触发事件,用户可以通过相应的菜单项 command 进行不同的操作。

<script setup lang="ts">
	import {
		type DropdownItemProps,
		type DropdownCommand,
		VrMessage,
	} from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]

	function handleCommand(command: DropdownCommand) {
		VrMessage.info('click on item ' + command)
	}
</script>

<template>
	<vr-dropdown :items="items" @command="handleCommand">
		<span class="dropdown-link">
			Dropdown List
			<vr-icon icon="angle-down" />
		</span>
	</vr-dropdown>
</template>

<style scoped>
	.dropdown-link {
		display: flex;
		align-items: center;
		cursor: pointer;
		color: var(--vr-color-primary);

		i {
			margin-left: 8px;
		}
	}
</style>

下拉方法

可以手动使用 DropdownInstance.openDropdownInstance.close 以打开或关闭下拉菜单


<script setup lang="ts">
	import type { DropdownItemProps, DropdownInstance } from 'veyra'
	import { ref } from 'vue'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]
	const dropdownRef = ref<DropdownInstance>()
</script>

<template>
	<vr-button @click="() => dropdownRef?.open()">open</vr-button>
	<vr-button @click="() => dropdownRef?.close()">close</vr-button>
	<br />
	<vr-dropdown ref="dropdownRef" :items="items">
		<span class="dropdown-link">
			Dropdown List
			<vr-icon icon="angle-down" />
		</span>
	</vr-dropdown>
</template>

<style scoped>
	.dropdown-link {
		display: flex;
		align-items: center;
		cursor: pointer;
		color: var(--vr-color-primary);
		margin-top: 20px;
		i {
			margin-left: 8px;
		}
	}
</style>

禁用状态

通过设置 disabled 属性来禁用下拉菜单。

disabled
undisabled

<script setup lang="ts">
	import { type DropdownItemProps } from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]
</script>

<template>
	<div class="row">
		<div class="col">
			<div class="desc">disabled</div>
			<vr-dropdown :items="items" disabled>
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
		<div class="col">
			<div class="desc">undisabled</div>
			<vr-dropdown :items="items">
				<span class="dropdown-link">
					Dropdown List
					<vr-icon icon="angle-down" />
				</span>
			</vr-dropdown>
		</div>
	</div>
</template>

<style scoped>
	.row {
		display: flex;
		flex-wrap: wrap;
	}
	.col {
		flex: 1;
	}
	.desc {
		display: block;
		color: var(--vr-text-color-secondary);
		font-size: 14px;
		margin-bottom: 20px;
	}
	.dropdown-link {
		display: flex;
		align-items: center;
		cursor: pointer;
		color: var(--vr-color-primary);
		i {
			margin-left: 8px;
		}
	}
</style>

触发对象

设置 split-button 属性来让触发下拉元素呈现为按钮组,左边是功能按钮,右边是触发下拉菜单的按钮。

<script setup lang="ts">
	import { type DropdownItemProps, VrMessage } from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]

	function handleClick() {
		VrMessage.info('button click')
	}
</script>

<template>
	<div class="row">
		<vr-dropdown :items="items">
			<vr-button type="primary">
				Dropdown List
				<vr-icon icon="angle-down" style="margin-left: 8px" />
			</vr-button>
		</vr-dropdown>
		<vr-dropdown
			:items="items"
			type="primary"
			@click="handleClick"
			split-button>
			Dropdown List
		</vr-dropdown>
	</div>
</template>

<style scoped>
	.row div {
		margin-right: 16px;
	}
</style>

尺寸

通过设置 size 属性来改变下拉菜单和按钮的尺寸。

<script setup lang="ts">
	import { type DropdownItemProps } from 'veyra'

	const items: DropdownItemProps[] = [
		{ command: '1', label: 'Action 1' },
		{ command: '2', label: 'Action 2' },
		{ command: '3', label: 'Action 3', disabled: true },
		{ command: '4', label: 'Action 4', divided: true },
	]
</script>

<template>
	<div class="row">
		<vr-dropdown :items="items" size="large" split-button>
			Large List
		</vr-dropdown>
		<vr-dropdown :items="items" split-button> Default List </vr-dropdown>
		<vr-dropdown :items="items" size="small" split-button>
			small List
		</vr-dropdown>
	</div>
</template>

<style scoped>
	.row div {
		margin-right: 16px;
	}
</style>

Props

NameDescriptionTypeDefault
type菜单按钮类型同 Button 组件 的 type--
size菜单尺寸同 Button 组件 的 size--
split-button下拉触发元素呈现为按钮booleanfalse
disabled是否禁用booleanfalse
trigger触发方式'hover' | 'click' | 'contextmenu'hover
placement弹出位置'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' |...bottom
hideOnClick点击菜单项时是否隐藏下拉菜单booleantrue
show-timeout展开下拉菜单的延时,仅在 trigger 为 hover 时有效number150
hide-timeout收起下拉菜单的延时,仅在 trigger 为 hover 时有效number150

TIP

ps: 触发方式为 hover 时,如果出现弹出层不稳定的情况,可能是 hide-timeout 值过小,请增大该值。(默认值 150 经过验证较为稳定)

Events

NameDescriptionType
clicksplit-buttton 为 true 时,点击左侧按钮触发(event: MouseEvent) => void
visible-change下拉菜单显示或隐藏时触发(visible: boolean) => void
command点击菜单项时触发(command: string| number) => void

Slots

NameDescriptionSub Component
default默认插槽-
dropdown下拉菜单DropdownItem

Expose

NameDescriptionType
open打开下拉菜单() => void
close关闭下拉菜单() => void

Props

NameDescriptionTypeDefault
command菜单项指令string | number-
label菜单项文本string-
disabled禁用状态booleanfalse
divider添加分割线booleanfalse

Slots

NameDescription
default默认插槽, 优先级高于 props.label