更新记录

1.0.5(2025-07-01) 下载此版本

更新文档

1.0.4(2025-05-26) 下载此版本

优化

1.0.3(2025-05-23) 下载此版本

1

查看更多

平台兼容性

uni-app(4.05)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 快应用-华为 快应用-联盟
-

其他

多语言 暗黑模式 宽屏模式
× ×

x-dropdown 组件使用说明

组件简介

x-dropdown 是一个灵活的下拉菜单组件,支持自定义触发器和菜单内容,提供智能定位和动画效果。

功能特性

  • ✅ 支持自定义触发器内容
  • ✅ 支持自定义菜单样式
  • ✅ 智能定位,自动调整菜单位置
  • ✅ 流畅的动画效果
  • ✅ 支持插槽自定义菜单内容
  • ✅ 完整的事件回调

基本使用

基础用法

<template>
  <x-dropdown 
    :menu-list="menuOptions"
    @menuClick="onMenuClick"
  >
    <view class="trigger">
      <text>点击选择</text>
      <text class="arrow">▼</text>
    </view>
  </x-dropdown>
</template>

<script>
export default {
  data() {
    return {
      menuOptions: ['选项一', '选项二', '选项三']
    }
  },
  methods: {
    onMenuClick(item) {
      console.log('选中了:', item.value, '索引:', item.index)
    }
  }
}
</script>

<style>
.trigger {
  display: flex;
  align-items: center;
  padding: 10px;
  background: #f5f5f5;
  border-radius: 4px;
}

.arrow {
  margin-left: 8px;
  font-size: 12px;
}
</style>

自定义菜单样式

<template>
  <x-dropdown 
    :menu-list="menuOptions"
    :menu-style="customMenuStyle"
    @menuClick="onMenuClick"
  >
    <view class="custom-trigger">
      自定义样式菜单
    </view>
  </x-dropdown>
</template>

<script>
export default {
  data() {
    return {
      menuOptions: ['红色', '绿色', '蓝色'],
      customMenuStyle: {
        backgroundColor: '#f0f0f0',
        borderRadius: '12px',
        border: '1px solid #ddd'
      }
    }
  },
  methods: {
    onMenuClick(item) {
      console.log('选择了颜色:', item.value)
    }
  }
}
</script>

使用插槽自定义菜单

<template>
  <x-dropdown @open="onOpen" @close="onClose">
    <view class="trigger">
      <text>自定义菜单</text>
    </view>

    <template #menu>
      <view class="custom-menu">
        <view class="menu-header">选择操作</view>
        <view 
          class="custom-menu-item"
          v-for="(item, index) in customMenuList"
          :key="index"
          @click="handleCustomClick(item, index)"
        >
          <image :src="item.icon" class="menu-icon" />
          <text class="menu-text">{{ item.label }}</text>
        </view>
      </view>
    </template>
  </x-dropdown>
</template>

<script>
export default {
  data() {
    return {
      customMenuList: [
        { label: '编辑', icon: '/static/edit.png' },
        { label: '删除', icon: '/static/delete.png' },
        { label: '分享', icon: '/static/share.png' }
      ]
    }
  },
  methods: {
    onOpen() {
      console.log('菜单打开')
    },
    onClose() {
      console.log('菜单关闭')
    },
    handleCustomClick(item, index) {
      console.log('点击了:', item.label)
      // 手动关闭菜单
      this.$refs.dropdown.close()
    }
  }
}
</script>

<style>
.custom-menu {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 20px rgba(0,0,0,0.1);
  overflow: hidden;
}

.menu-header {
  padding: 12px 16px;
  background: #f8f8f8;
  font-size: 14px;
  color: #666;
  border-bottom: 1px solid #eee;
}

.custom-menu-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
}

.custom-menu-item:active {
  background: #f0f0f0;
}

.menu-icon {
  width: 20px;
  height: 20px;
  margin-right: 12px;
}

.menu-text {
  font-size: 16px;
  color: #333;
}
</style>

属性说明

属性名 类型 默认值 说明
menuList Array ['菜单1', '菜单2', '菜单3'] 菜单选项列表
menuStyle Object {} 菜单项的自定义样式
interspace String/Number '10rpx' 菜单与触发器的间距
customStyle Object/String - 触发器的自定义样式

menuList 数据格式

支持以下两种数据格式:

// 简单字符串数组
menuList: ['选项1', '选项2', '选项3']

// 对象数组(推荐)
menuList: [
  { label: '选项1', value: 'option1' },
  { label: '选项2', value: 'option2' },
  { label: '选项3', value: 'option3' }
]

事件说明

事件名 说明 回调参数
@open 菜单打开时触发 -
@close 菜单关闭时触发 -
@change 菜单状态改变时触发 Boolean - 是否打开
@menuClick 点击菜单项时触发 { value, index } - 菜单项值和索引

插槽说明

插槽名 说明
默认插槽 触发器内容
menu 自定义菜单内容

方法说明

方法名 说明 参数
close() 手动关闭菜单 -

使用方法:

// 通过 ref 调用
this.$refs.dropdown.close()

完整示例

<template>
  <view class="page">
    <view class="demo-section">
      <text class="section-title">基础下拉菜单</text>
      <x-dropdown 
        ref="basicDropdown"
        :menu-list="basicMenuList"
        :interspace="20"
        @open="downOpen"
        @close="downClose"
        @change="downChange"
        @menuClick="onBasicMenuClick"
      >
        <view class="basic-trigger">
          <text>{{ selectedValue || '请选择' }}</text>
          <text class="dropdown-arrow" :class="{ 'rotate': isOpen }">▼</text>
        </view>
      </x-dropdown>
    </view>

    <view class="demo-section">
      <text class="section-title">自定义样式菜单</text>
      <x-dropdown 
        :menu-list="colorMenuList"
        :menu-style="colorMenuStyle"
        @menuClick="onColorMenuClick"
      >
        <view class="color-trigger" :style="{ backgroundColor: selectedColor }">
          选择颜色
        </view>
      </x-dropdown>
    </view>

    <view class="demo-section">
      <text class="section-title">完全自定义菜单</text>
      <x-dropdown ref="customDropdown" @open="onCustomOpen">
        <view class="custom-trigger">
          <image src="/static/more.png" class="more-icon" />
        </view>

        <template #menu>
          <view class="action-menu">
            <view 
              class="action-item"
              v-for="(action, index) in actionList"
              :key="index"
              @click="handleAction(action, index)"
            >
              <image :src="action.icon" class="action-icon" />
              <text class="action-text">{{ action.name }}</text>
            </view>
          </view>
        </template>
      </x-dropdown>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      isOpen: false,
      selectedValue: '',
      selectedColor: '#f0f0f0',
      basicMenuList: ['首页', '产品', '服务', '关于我们'],
      colorMenuList: ['红色', '绿色', '蓝色', '黄色'],
      colorMenuStyle: {
        backgroundColor: '#fff',
        borderRadius: '8px',
        border: '2px solid #e0e0e0'
      },
      actionList: [
        { name: '编辑', icon: '/static/edit.png', action: 'edit' },
        { name: '复制', icon: '/static/copy.png', action: 'copy' },
        { name: '删除', icon: '/static/delete.png', action: 'delete' }
      ]
    }
  },
  methods: {
    downOpen() {
      console.log('基础菜单打开')
    },
    downClose() {
      console.log('基础菜单关闭')
    },
    downChange(isOpen) {
      this.isOpen = isOpen
      console.log('菜单状态:', isOpen ? '打开' : '关闭')
    },
    onBasicMenuClick(item) {
      this.selectedValue = item.value
      console.log('选择了:', item.value, '索引:', item.index)
    },
    onColorMenuClick(item) {
      const colorMap = {
        '红色': '#ff4757',
        '绿色': '#2ed573',
        '蓝色': '#3742fa',
        '黄色': '#ffa502'
      }
      this.selectedColor = colorMap[item.value] || '#f0f0f0'
      console.log('选择了颜色:', item.value)
    },
    onCustomOpen() {
      console.log('自定义菜单打开')
    },
    handleAction(action, index) {
      console.log('执行操作:', action.action)

      switch(action.action) {
        case 'edit':
          this.handleEdit()
          break
        case 'copy':
          this.handleCopy()
          break
        case 'delete':
          this.handleDelete()
          break
      }

      // 关闭菜单
      this.$refs.customDropdown.close()
    },
    handleEdit() {
      uni.showToast({ title: '编辑操作', icon: 'none' })
    },
    handleCopy() {
      uni.showToast({ title: '复制成功', icon: 'success' })
    },
    handleDelete() {
      uni.showModal({
        title: '确认删除',
        content: '确定要删除这个项目吗?',
        success: (res) => {
          if (res.confirm) {
            uni.showToast({ title: '删除成功', icon: 'success' })
          }
        }
      })
    }
  }
}
</script>

<style>
.page {
  padding: 20px;
}

.demo-section {
  margin-bottom: 40px;
}

.section-title {
  display: block;
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 16px;
  color: #333;
}

.basic-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 6px;
  min-width: 120px;
}

.dropdown-arrow {
  font-size: 12px;
  color: #666;
  transition: transform 0.3s;
}

.dropdown-arrow.rotate {
  transform: rotate(180deg);
}

.color-trigger {
  padding: 12px 20px;
  color: white;
  text-align: center;
  border-radius: 6px;
  min-width: 100px;
}

.custom-trigger {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f5f5f5;
  border-radius: 20px;
}

.more-icon {
  width: 20px;
  height: 20px;
}

.action-menu {
  background: white;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0,0,0,0.15);
  overflow: hidden;
  min-width: 120px;
}

.action-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid #f0f0f0;
}

.action-item:last-child {
  border-bottom: none;
}

.action-item:active {
  background: #f8f8f8;
}

.action-icon {
  width: 18px;
  height: 18px;
  margin-right: 12px;
}

.action-text {
  font-size: 16px;
  color: #333;
}
</style>

注意事项

  1. 定位机制:组件会自动检测屏幕边界,智能调整菜单位置
  2. 动画效果:内置了流畅的展开/收起动画
  3. 点击关闭:点击遮罩层会自动关闭菜单
  4. 自定义菜单:使用插槽时需要手动调用 close() 方法关闭菜单
  5. 样式优先级menuStyle 属性只对默认菜单生效,插槽菜单需要自定义样式

插件如果对你有帮助给个好评吧~

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问