Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
visible: false
disabled: false
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

组件集

v-dropdown 组件提供的组件集

  • Dropdown dropdown 的主容器
  • DropdownTrigger dropdown 内置的按钮形态的触发器
  • DropdownContent 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>
  <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>
  /** Adjust content position */
  adjust: () => void
  /** Open dropdown */
  open: () => void
  /** Close dropdown */
  close: () => void
  /** Toggle dropdown open and close */
  toggleVisible: () => 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 true
   */
  animated?: boolean
  /**
   * 触发器与下拉栏之间的间距
   * @default 5
   */
  gap?: number
  /**
   * 目标容器
   * @default `body`
   */
  appendTo: string | HTMLElement
}

DropdownContent 组件的 props

ts
interface ContentProps {
  /**
   * 下拉栏的边框
   * @default true
   */
  border?: 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>

open

打开下拉栏

ts
open: () => void

close

关闭下拉栏

ts
close: () => void

toggleVisible

循环切换下拉栏状态

ts
toggleVisible: () => void

Released under the MIT License.