Skip to content

Dropdown

下拉菜单组件

GitHub Repo stars GitHub forks

项目状态

test codecov npm version license JavaScript Style Guide

版本更新内容请访问 Changelog

如果您的项目正在使用 vue 2.x 版本生态,请使用 v-dropdown 2.x 版本

安装

v-dropdown 组件安装到项目中

sh
npm i v-dropdown
sh
yarn add v-dropdown
sh
pnpm add v-dropdown

常规用例

template
<Dropdown @visible-change="change">
  <!-- trigger element -->
  <template #trigger>
    <!-- built-in trigger button -->
    <DropdownTrigger />
  </template>

  <!-- contents display in dropdown -->
  <DropdownContent>
    <div>
      some contents
    </div>
  </DropdownContent>
</Dropdown>
js
import { Dropdown, DropdownContent, DropdownTrigger } from 'v-dropdown'

function change (val) {
  console.log(val)
}

实例

快速应用

Dropdown 组件默认使用点击触发对象的方式以打开下拉栏

template
<Dropdown>
  <template #trigger>
    <DropdownTrigger>Click me</DropdownTrigger>
  </template>
  <DropdownContent>
    <div>some contents</div>
  </DropdownContent>
</Dropdown>

鼠标悬停激活

鼠标悬停触发对象区域以打开下拉栏

template
<Dropdown trigger="hover">
  <template #trigger>
    <DropdownTrigger>Hover me</DropdownTrigger>
  </template>
  ...
</Dropdown>

鼠标右键激活

鼠标右键点击触发对象区域以打开下拉栏

Mouse right click me
template
<Dropdown
  trigger="contextmenu"
  block
>
  <template #trigger>
    <div
      style="height: 10rem;"
      class="
        d-flex align-items-center justify-content-center
        bg-light rounded-3 px-3 py-1 fs-1 text-body-secondary w-100
      "
    >Mouse right click me</div>
  </template>
  ...
</Dropdown>

关闭循环切换

设置点击触发对象循环切换下拉栏的打开与关闭,效果同样作用于鼠标悬停与鼠标右键菜单的触发模式

template
<Dropdown :toggle="false" >
  ...
</Dropdown>

禁用

template
<Dropdown :disabled="true" >
  ...
</Dropdown>

手动模式

在这个例子里,只有输入数字 3 时,才会打开下拉栏

template
<Dropdown
  :manual="true"
  ref="dropdown"
>
  <template #trigger>
    <input
      type="text"
      @input="inputChange"
    />
  </template>
  ...
</Dropdown>
js
import { ref } from 'vue'
const dropdown = ref(null)

function inputChange (e) {
  if (e.target.value === '3') {
    dropdown.value.display()
  } else {
    // Dropdown expose `visible` state
    if (dropdown.value.visible) {
      dropdown.value.close()
    }
  }
}

对齐方向

下拉栏对齐于触发器的方向

Align direction:
html
<Dropdown align="center" >
  ...
</Dropdown>

样式定制

Trigger rounded:
Content rounded:
template
<Dropdown>
  <template #trigger>
    <DropdownTrigger rounded="pill" />
  </template>
  <DropdownContent
    :border="false"
    rounded="medium"
  >
    <div>some contents</div>
  </DropdownContent>
</Dropdown>

更具体的样式定制可直接通过 styleclass 来设置

template
<Dropdown>
  <template #trigger>
    <DropdownTrigger class="border rounded-4 bg-primary-subtle p-2" />
  </template>
  <DropdownContent
    style="width: 500px;background-color:rgb(255, 174, 0);"
  >
    <div>some contents</div>
  </DropdownContent>
</Dropdown>

状态与函数

Dropdown 的 trigger 与默认插槽均提供了插件的状态与部分功能函数

template
<Dropdown>
  <template #trigger="{ visible, disabled, close }">
    <DropdownTrigger />
  </template>
  <template #default="{ visible, disabled, close }">
    <DropdownContent>
      <div>visible: {{ visible }}</div>
      <div>disabled: {{ disabled }}</div>
      <button
        class="btn btn-secondary"
        @click="close"
      >Close</button>
    </DropdownContent>
  </template>
</Dropdown>

另外,Dropdown 还提供了 useDropdown 组合式函数,用于在组件内获取下拉栏的状态与函数

template
<Dropdown>
  <template #trigger>
    <DropdownTrigger />
  </template>
  <DropdownContent>
    <CustomContent />
  </DropdownContent>
</Dropdown>
vue
<template>
  <div>
    <div>visible: {{ visible }}</div>
    <div>disabled: {{ disabled }}</div>
    <button
      class="btn btn-secondary"
      @click="close"
    >Close</button>
  </div>
</template>
<script setup>
import { useDropdown } from 'v-dropdown'

const { visible, disabled, close } = useDropdown()
</script>

插槽

  • trigger 触发器
  • default 下拉栏内容

Dropdown 组件为 triggerdefault 插槽均提供了插件的状态与部分功能函数

ts
interface DropdownUtilities {
  visible: ComputedRef<boolean>
  disabled: ComputedRef<boolean>
  /** Close the dropdown */
  close: () => void
  /** Adjust content position */
  adjust: () => void
}

应用作用域数据状态

vue
<template>
  <Dropdown>
    <template #trigger="data: DropdownUtilities">
      <button type="button">visible: {{ data.visible }}</button>
    </template>

    <template #default="{ visible, disabled, close }: DropdownUtilities">
      <div>visible: {{ visible }}</div>
      <div>disabled: {{ disabled }}</div>
      <button
        class="btn btn-secondary"
        @click="close"
      >Close</button>
    </template>
  </Dropdown>
</template>
<script setup lang="ts">
import type { DropdownUtilities } from 'v-dropdown'
</script>

adjust 函数用于调整下拉栏内容位置,使其与触发器对齐

提示

在绝大多数情况下,触发器与下拉栏内容的位置与尺寸发生变化时,组件会自动调整下拉栏内容位置,所以只推荐在业务交互较复杂的场景下,下拉栏的位置不符合预期时使用

DropdownTriggerDropdown 组件内置的按钮形态的触发器对象组件

  • default 触发器内容,默认显示 Open 文本
  • append Dropdown 下拉栏打开状态图标
  • default 下拉栏内容

Props

Dropdown 组件的 props

ts
interface DropdownProps {
  /**
   * 下拉栏的对齐方向
   * @default `left`
   */
  align?: 'left' | 'center' | 'right'
  /**
   * 连续点击触发器时是否循环切换打开与关闭
   * @default true
   */
  toggle?: boolean
  /**
   * 手动控制下拉栏的显示与隐藏
   * @default false
   */
  manual?: boolean
  /**
   * 禁用状态
   * @default false
   */
  disabled?: boolean
  /**
   * 触发器显示全宽模式
   * @default false
   */
  block?: boolean
  /**
   * 下拉栏的触发方式
   * @default `click`
   */
  trigger?: 'click' | 'hover' | 'contextmenu'
  /**
   * 触发器与下拉栏之间的间距
   * @default 5
   */
  gap?: number
  /**
   * 目标容器
   * @default `body`
   */
  appendTo: string | HTMLElement
}

DropdownContent 组件的 props

ts
interface ContentProps {
  /**
   * 下拉栏的边框
   * @default true
   */
  border?: boolean
  /**
   * 下拉栏的打开与关闭是否使用动画
   * @default true
   */
  animated?: boolean
  /**
   * 下拉栏的圆角弧度
   * @default `small`
   */
  rounded?: 'small' | 'medium' | 'large'
  /**
   * 下拉栏的 Z 轴顺序值
   * @default 3000
   */
  zIndex?: number
}

DropdownTrigger 组件的 props

ts
interface TriggerProps {
  /** 触发器按钮的圆角弧度 */
  rounded?: 'small' | 'medium' | 'large' | 'pill' | 'circle'
}

事件

组件各类操作响应事件

visible-change

响应下拉栏打开 / 关闭的状态变化

ts
`visible-change`: (visible: boolean) => void

open

下拉栏打开时响应

ts
open: () => void

opened

下拉栏打开动画完成时响应

ts
opened: () => void

close

下拉栏关闭时响应

ts
close: () => void

closed

下拉栏关闭动画完成时响应

ts
closed: () => void

API

使用插件的 API 前,需为组件声明 ref 属性,并使用 ref() 声明对应名称的响应式变量以调用 API 方法

vue
<template>
  <Dropdown ref="dropdown" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { Dropdown } from 'v-dropdown'

const dropdown = ref(null)
onMounted(() => {
  dropdown.value.display()
})
</script>

display

打开下拉栏

ts
display: () => void

close

关闭下拉栏

ts
close: () => void

toggleVisible

循环切换下拉栏状态

ts
toggleVisible: () => void

Released under the MIT License.