xtf-bubble-menu
组件说明
xtf-bubble-menu 是气泡菜单组件,点击或悬浮触发元素后弹出深色气泡面板展示操作列表。支持 8 个弹出方向、箭头指示、图标/图片/描述、关闭拦截和插槽定制,适用于工具栏操作、右键菜单和更多操作等场景。
基础用法
1. 最简示例
通过 actions 传入菜单项,包裹触发元素即可:
vue
<template>
<xtf-bubble-menu :actions="actions" @select="onSelect">
<xtf-button size="small">更多操作</xtf-button>
</xtf-bubble-menu>
</template>
<script>
export default {
data() {
return {
actions: [
{ label: '编辑', key: 'edit', icon: 'edit' },
{ label: '复制', key: 'copy', icon: 'content-copy' },
{ label: '删除', key: 'delete', icon: 'delete', danger: true }
]
}
},
methods: {
onSelect({ action, index }) {
uni.showToast({ title: '选择了: ' + action.label, icon: 'none' })
}
}
}
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2. 弹出方向与箭头
通过 placement 设置弹出方向(8 个方位),通过 arrow 控制是否显示箭头:
vue
<template>
<view style="display: flex; gap: 24rpx; flex-wrap: wrap">
<xtf-bubble-menu :actions="actions" placement="bottom-start" @select="onSelect">
<xtf-button size="small">下左</xtf-button>
</xtf-bubble-menu>
<xtf-bubble-menu :actions="actions" placement="bottom" @select="onSelect">
<xtf-button size="small">下中</xtf-button>
</xtf-bubble-menu>
<xtf-bubble-menu :actions="actions" placement="bottom-end" @select="onSelect">
<xtf-button size="small">下右</xtf-button>
</xtf-bubble-menu>
<xtf-bubble-menu :actions="actions" placement="top" :arrow="false" @select="onSelect">
<xtf-button size="small">上无箭头</xtf-button>
</xtf-bubble-menu>
</view>
</template>
<script>
export default {
data() {
return {
actions: [
{ label: '选项一', key: '1' },
{ label: '选项二', key: '2' },
{ label: '选项三', key: '3' }
]
}
},
methods: {
onSelect({ action }) {
console.log('选择了:', action.key)
}
}
}
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
3. 带图标、图片和描述
actions 每项支持 icon、image、description 字段丰富菜单项显示:
vue
<template>
<xtf-bubble-menu :actions="actions" @select="onSelect">
<xtf-button size="small">分享</xtf-button>
</xtf-bubble-menu>
</template>
<script>
export default {
data() {
return {
actions: [
{ label: '微信好友', key: 'wechat', icon: 'wechat', description: '发送给好友' },
{ label: '朋友圈', key: 'moment', icon: 'moment', description: '分享到朋友圈' },
{ label: '复制链接', key: 'copy', icon: 'link', description: '复制到剪贴板' },
{ label: '举报', key: 'report', icon: 'warning', description: '举报不良内容', danger: true }
]
}
},
methods: {
onSelect({ action }) {
console.log('选择了:', action.key)
}
}
}
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
4. 手动控制与关闭拦截
通过 v-model:show 手动控制显隐,通过 beforeClose 拦截关闭行为:
vue
<template>
<view>
<xtf-bubble-menu
v-model:show="show"
trigger="manual"
:actions="actions"
:before-close="beforeClose"
@select="onSelect"
>
<xtf-button size="small" @click="show = true">打开菜单</xtf-button>
</xtf-bubble-menu>
</view>
</template>
<script>
export default {
data() {
return {
show: false,
actions: [
{ label: '保存', key: 'save' },
{ label: '删除', key: 'delete', danger: true }
]
}
},
methods: {
async beforeClose({ type }) {
if (type === 'select') {
const res = await new Promise((resolve) => {
uni.showModal({
title: '确认',
content: '确认执行此操作?',
success: (r) => resolve(r.confirm)
})
})
return res
}
return true
},
onSelect({ action }) {
console.log('选择了:', action.key)
}
}
}
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
5. 自定义面板内容
通过 content 插槽完全自定义面板内容:
vue
<template>
<xtf-bubble-menu :actions="[]" placement="bottom-start">
<xtf-button size="small">自定义面板</xtf-button>
<template #content>
<view style="padding: 24rpx; min-width: 300rpx">
<xtf-text level="body" style="color: #fff">自定义内容区域</xtf-text>
<view style="margin-top: 16rpx; display: flex; gap: 12rpx">
<xtf-button size="small" type="primary" label="确认" />
<xtf-button size="small" type="light" label="取消" />
</view>
</view>
</template>
</xtf-bubble-menu>
</template>1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
全部属性
| 属性 | 类型 | 默认值 | 作用描述 | 适用范围 |
|---|---|---|---|---|
show | Boolean | false | 是否显示面板,支持 v-model:show 双向绑定 | 控制显隐 |
trigger | String | 'click' | 触发方式:'click' 点击 / 'hover' 悬浮(H5) / 'manual' 手动 | 控制触发行为 |
placement | String | 'bottom' | 弹出方向:'top-start' / 'top' / 'top-end' / 'right' / 'bottom-start' / 'bottom' / 'bottom-end' / 'left' | 控制弹出位置 |
actions | Array | [] | 菜单项数组,每项字段见下方子表 | 核心数据源 |
width | String | Number | 280 | 面板宽度(rpx) | 控制面板宽度 |
maxWidth | String | Number | '' | 面板最大宽度(rpx) | 限制最大宽度 |
offset | String | Number | 16 | 面板与触发元素的间距(rpx) | 调整间距 |
zIndex | String | Number | 12060 | 面板层级 | 处理遮挡问题 |
transitionDuration | String | Number | 220 | 过渡动画时长(毫秒) | 调整动画速度 |
arrow | Boolean | true | 是否显示箭头 | 控制箭头显隐 |
disabled | Boolean | false | 是否禁用触发 | 禁用菜单 |
closeOnClickOutside | Boolean | true | 是否点击外部关闭 | 防止误关闭 |
closeOnClickAction | Boolean | true | 是否点击菜单项后自动关闭 | 手动控制关闭 |
beforeClose | Function | null | 关闭前拦截函数,接收 { type, action, index },返回 false 阻止关闭 | 二次确认 |
iconSize | String | Number | 'sm' | 菜单项图标大小 | 自定义图标大小 |
showIcon | Boolean | true | 是否显示菜单项图标 | 隐藏图标 |
imageSize | String | Number | 32 | 菜单项图片大小(rpx) | 自定义图片大小 |
showSuffix | Boolean | true | 是否显示后缀箭头图标 | 隐藏后缀图标 |
suffixIcon | String | 'keyboard_arrow_right' | 后缀图标名 | 自定义后缀图标 |
customClass | String | '' | 根元素自定义类名 | 样式覆盖 |
customStyle | String | Object | '' | 根元素自定义样式 | 动态样式覆盖 |
panelClass | String | '' | 面板自定义类名 | 面板样式定制 |
panelStyle | String | Object | '' | 面板自定义样式 | 面板样式定制 |
listClass | String | '' | 列表自定义类名 | 列表样式定制 |
listStyle | String | Object | '' | 列表自定义样式 | 列表样式定制 |
itemClass | String | Function | '' | 菜单项自定义类名,支持函数 (action, index) => className | 细粒度样式定制 |
itemStyle | String | Object | Function | '' | 菜单项自定义样式,支持函数 (action, index) => styleObj | 细粒度样式定制 |
iconClass | String | '' | 图标自定义类名 | 图标样式定制 |
iconStyle | String | Object | '' | 图标自定义样式 | 图标样式定制 |
imageClass | String | '' | 图片自定义类名 | 图片样式定制 |
imageStyle | String | Object | '' | 图片自定义样式 | 图片样式定制 |
labelClass | String | '' | 标签自定义类名 | 标签样式定制 |
labelStyle | String | Object | '' | 标签自定义样式 | 标签样式定制 |
suffixIconClass | String | '' | 后缀图标自定义类名 | 后缀图标样式定制 |
suffixIconStyle | String | Object | '' | 后缀图标自定义样式 | 后缀图标样式定制 |
arrowClass | String | '' | 箭头自定义类名 | 箭头样式定制 |
arrowStyle | String | Object | '' | 箭头自定义样式 | 箭头样式定制 |
actions 数组每项支持的字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | String | — | 菜单项主文案(必填),也兼容 name |
key | String | — | 唯一标识,也兼容 value |
description | String | '' | 辅助描述文字,也兼容 desc |
icon | String | '' | 左侧图标名 |
image | String | '' | 左侧图片地址,也兼容 img,设置后替代图标 |
imageMode | String | 'aspectFit' | 图片填充模式 |
theme | String | '' | 图标主题 |
color | String | '' | 图标颜色 |
danger | Boolean | false | 是否为危险操作项,显示红色 |
disabled | Boolean | false | 是否禁用 |
keepOpen | Boolean | false | 点击后是否保持面板打开 |
showIcon | Boolean | 继承 showIcon | 单项是否显示图标 |
showSuffix | Boolean | 继承 showSuffix | 单项是否显示后缀图标 |
suffixIcon | String | 继承 suffixIcon | 单项自定义后缀图标 |
事件
| 事件名称 | 触发时机 | 回调参数 | 参数说明 |
|---|---|---|---|
update:show | v-model:show 值变更时触发 | (value: Boolean) | value 为新的显隐状态 |
open | 面板打开时触发 | 无 | — |
close | 面板关闭时触发 | 无 | — |
select | 点击菜单项时触发(disabled 项不触发) | (payload: { index: Number, action: Object }) | index 为点击项索引,action 为原始数据对象 |
事件使用示例
vue
<template>
<xtf-bubble-menu
v-model:show="show"
:actions="actions"
@open="onOpen"
@close="onClose"
@select="onSelect"
>
<xtf-button label="更多操作" />
</xtf-bubble-menu>
</template>
<script>
export default {
data() {
return { show: false, actions: [{ label: '编辑', key: 'edit' }] }
},
methods: {
onOpen() {
console.log('菜单打开')
},
onClose() {
console.log('菜单关闭')
},
onSelect({ action }) {
uni.showToast({ title: action.label, icon: 'none' })
}
}
}
</script>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
插槽
| 插槽名 | 作用域参数 | 说明 |
|---|---|---|
| 默认插槽 | 无 | 菜单触发元素。 |
content | { actions, select } | 替换整个菜单面板内容。 |
item | { action, index } | 替换单个菜单项。 |
主题说明
- 面板背景为
rgba(12, 12, 14, 0.96)深色半透明 - 箭头背景与面板一致
- 面板阴影为
0 18rpx 42rpx rgba(15, 23, 42, 0.28) - 菜单项文字颜色为
#ffffff,描述文字为rgba(255, 255, 255, 0.68) - 危险项文字颜色为
#ff8d8d - 禁用项不透明度为 0.45
- 分隔线颜色为
rgba(255, 255, 255, 0.08) - 后缀图标颜色为
rgba(255, 255, 255, 0.72) - 面板圆角 24rpx,过渡动画使用
var(--xtf-bubble-menu-duration)
如需全局调整主题,请在 xtf-config-provider 或主题配置中覆盖上述 CSS 变量。