更新记录
1.0.0(2026-07-21)
首发版本。
- 提供 uni-app x UTS 标准组件模式的右侧操作列表项。
- 支持左滑展开、右滑关闭、方向锁定、速度判定和越界阻尼。
- 支持多个操作按钮同步展开、按钮禁用和
right插槽自定义操作区域。 - 支持
action、open、close、change、tap等交互事件。 - 支持
modelValue/v-model受控开合状态。 - 支持页面级打开、关闭、切换、关闭激活项和获取激活索引。
- 支持组件实例的
open、close、toggle、closeActive和getActiveIndex方法。 - 支持删除淡出与高度收缩动画,并通过
deleteAnimationEnd通知页面删除业务数据。 - 支持 Android、iOS、Web 和微信小程序。
平台兼容性
uni-app x(3.8.0)
| Chrome | Chrome插件版本 | Safari | Safari插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 微信小程序 | 微信小程序插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|
| √ | 1.0.0 | √ | 1.0.0 | 5.0 | 1.0.0 | 12 | 1.0.0 | × | √ | 1.0.0 |
其他
| 多语言 | 暗黑模式 | 宽屏模式 |
|---|---|---|
| × | × | √ |
丝滑右滑操作 - uni-app x
kongbai-swipe-action 是一个面向 uni-app x 的 UTS 标准组件,用于为消息、通讯录、待办、订单等列表项添加右侧操作按钮。
组件负责手势识别、方向锁定、速度判定、阻尼回弹、活动项互斥和删除动画;业务数据的修改由页面通过事件自行处理。
特性
- 左滑展开右侧操作按钮,右滑关闭已展开项。
- 多个操作按钮从第一像素开始同步展开和收回,并按宽度平均分配。
- 支持慢速拖动阈值、快速滑动判定和越界阻尼。
- 同一页面始终只保留一个激活项,打开新项时自动关闭旧项。
- 支持普通操作事件、受控开合、页面级索引控制和组件实例方法。
- 支持删除淡出与高度收缩动画,动画结束后由页面删除业务数据。
- 支持内置操作按钮和
right插槽自定义操作区域。
安装与使用
通过插件市场导入后,组件可以直接使用 easycom,无需手动注册。组件适用于 uni-app x,不适用于普通 uni-app Vue 项目。
最小示例
<template>
<kongbai-swipe-action
v-for="(item, index) in list"
:key="item.id"
:index="index"
:action-width="88"
:actions="actions"
:close-on-action="false"
@action="onAction(index, $event)"
@deleteAnimationEnd="onDeleteAnimationEnd(item.id)">
<view class="row">
<text>{{ item.title }}</text>
</view>
</kongbai-swipe-action>
</template>
<script setup lang="uts">
import { closeSwipeAction } from '@/uni_modules/kongbai-swipe-action'
type Item = {
id : number
title : string
}
const actions : UTSJSONObject[] = [
{ key: 'more', text: '更多', backgroundColor: '#6B7280', color: '#FFFFFF', disabled: false, deleteAnimation: false } as UTSJSONObject,
{ key: 'delete', text: '删除', backgroundColor: '#FF4D4F', color: '#FFFFFF', disabled: false, deleteAnimation: true } as UTSJSONObject
]
const list = ref<Item[]>([
{ id: 1, title: '第一条消息' },
{ id: 2, title: '第二条消息' }
])
// 自定义组件事件在模板侧通常推断为 Any,在页面事件边界转换为 UTSJSONObject。
function onAction(index : number, event : any) : void {
if (index < 0 || index >= list.value.length) return
const actionEvent = event as UTSJSONObject
const key = actionEvent.getString('key') ?? ''
if (key == 'more') {
// 在这里处理业务操作,例如打开详情、弹出菜单或标记状态。
}
closeSwipeAction(index)
}
// deleteAnimationEnd 触发后再修改列表,避免数据提前变化打断删除动画。
function onDeleteAnimationEnd(id : number) : void {
for (let index = 0; index < list.value.length; index++) {
if (list.value[index].id == id) {
list.value.splice(index, 1)
break
}
}
}
</script>
Item 是用于帮助 uni-app x 识别 v-for 字段的简单类型声明,不需要定义类或构造函数。actions 必须声明为 UTSJSONObject[],每个按钮对象使用 as UTSJSONObject,避免 Android/iOS 端生成不同运行时对象类型。
操作按钮
每个操作按钮支持以下字段:
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
key |
string |
'' |
按钮唯一标识,会在事件参数中返回。 |
text |
string |
'' |
按钮文字,宽度不足时自动隐藏,不换行。 |
backgroundColor |
string |
#1677FF |
按钮背景颜色。 |
color |
string |
#FFFFFF |
按钮文字颜色。 |
disabled |
boolean |
false |
是否禁用按钮。禁用后不会触发操作事件。 |
deleteAnimation |
boolean |
false |
是否执行删除淡出和高度收缩动画。 |
多个按钮会平均分配操作面板宽度,并同步展开和收回。按钮总宽度最大为 480px。
如果不需要内置按钮,可以不传 actions,改用 right 插槽:
<kongbai-swipe-action :action-width="88">
<view class="row"><text>列表内容</text></view>
<template #right>
<view class="custom-action" @tap="onCustomAction">
<text>自定义操作</text>
</view>
</template>
</kongbai-swipe-action>
组件属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
actions |
UTSJSONObject[] |
[] |
右侧内置操作按钮数组。 |
index |
number |
-1 |
宿主列表索引,用于页面级主动控制。使用 v-for 时建议传入 index。 |
actionWidth |
number |
80 |
单个按钮宽度,单位为 px;多个按钮的总宽度按数量计算。单个按钮范围为 1 - 240px。 |
threshold |
number |
0.42 |
关闭状态下,慢速左滑达到该比例时打开,范围为 0.1 - 0.9。 |
modelValue |
boolean |
false |
受控开合状态,可使用 v-model。 |
disabled |
boolean |
false |
禁用手势和组件实例的打开方法。 |
closeOnAction |
boolean |
true |
点击普通操作按钮后是否自动关闭。 |
closeOnTap |
boolean |
true |
已展开时点击内容区域是否自动关闭。 |
受控开合
<kongbai-swipe-action v-model="opened" :actions="actions">
<view class="row"><text>受控列表项</text></view>
</kongbai-swipe-action>
const opened = ref<boolean>(false)
事件
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue |
boolean |
受控模式下同步开合状态。 |
open |
{ open: boolean } |
当前项打开。 |
close |
{ open: boolean } |
当前项关闭。 |
change |
{ open: boolean } |
当前项开合状态发生变化。 |
action |
{ key, index, action } |
点击未开启删除动画的普通按钮。 |
tap |
{ open: boolean } |
点击内容区域。 |
deleteAnimationEnd |
{ key, index, action } |
删除动画完成。页面应在此时移除对应业务数据。 |
action 和 deleteAnimationEnd 的 index 是操作按钮在 actions 数组中的位置,不是列表项索引。列表项索引通过组件的 index 属性传入,并用于页面级控制。
页面级主动控制(按 index)
页面级方法通过组件的 index 属性定位列表项,不需要为 v-for 的每一项创建 ref。适合批量列表、外部工具栏和业务状态统一控制:
import {
openSwipeAction,
closeSwipeAction,
toggleSwipeAction,
closeActiveSwipeAction,
getActiveSwipeActionIndex
} from '@/uni_modules/kongbai-swipe-action'
openSwipeAction(2) // 打开 index 为 2 的列表项
closeSwipeAction(2) // 关闭 index 为 2 的列表项
toggleSwipeAction(2) // 切换 index 为 2 的列表项
closeActiveSwipeAction() // 关闭当前激活项
const activeIndex = getActiveSwipeActionIndex() // 没有激活项时为 -1
页面级索引对应组件的 index 属性,不是业务数据的 id。当列表增删或排序后,请确保组件的 index 与当前渲染顺序一致。
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
openSwipeAction(index) |
number |
void |
打开指定列表索引项。 |
closeSwipeAction(index) |
number |
void |
关闭指定列表索引项。 |
toggleSwipeAction(index) |
number |
void |
切换指定列表索引项。 |
closeActiveSwipeAction() |
无 | void |
关闭当前激活项。 |
getActiveSwipeActionIndex() |
无 | number |
获取当前激活项索引,无激活项时返回 -1。 |
页面级方法与下面的组件实例方法不是重复调用:前者通过列表 index 找组件,后者通过 ref 找组件。index 是列表索引,不是业务数据的 id。
组件实例方法(按 ref)
组件仍然暴露 open() 方法,没有被页面级 API 替代。通过组件 ref 获取实例后,可以直接操作当前组件:
| 方法 | 返回值 | 说明 |
|---|---|---|
open() |
void |
打开当前 ref 对应的组件。 |
close() |
void |
关闭当前 ref 对应的组件。 |
toggle() |
void |
切换当前 ref 对应的组件。 |
closeActive() |
void |
关闭当前页面的激活项;它是页面级关闭方法的实例兼容入口。 |
getActiveIndex() |
number |
获取当前页面激活项索引;它是页面级查询方法的实例兼容入口,没有激活项时返回 -1。 |
两种调用方式对照
// 页面级:适合 v-for,通过 index 定位列表项。
openSwipeAction(2)
closeSwipeAction(2)
// 实例级:适合已经通过 ref 拿到的某一个组件,直接调用 open/close/toggle。
swipeRef.value?.open()
swipeRef.value?.close()
swipeRef.value?.toggle()
如果页面渲染的是 v-for 列表,优先使用页面级方法;如果只需要控制某一个明确的组件实例,再使用 ref 实例方法。closeActive() 和 getActiveIndex() 无论从哪里调用,查询的都是当前页面的全局激活项。
删除动画
给操作按钮设置 deleteAnimation: true 后,组件会:
- 自动读取当前列表项的实际高度。
- 让内容淡出并平滑收缩行高。
- 在视觉动画完成后触发
deleteAnimationEnd。 - 由页面在回调中删除业务数组中的对应数据。
组件不会自动修改页面的 list,也不需要额外传入行高。建议通过业务 id 删除,而不是直接使用事件中的列表索引,避免异步动画期间列表顺序变化导致误删。
交互与性能
- 拖动过程直接更新内容层位移和操作面板宽度,减少 Vue 响应式重渲染。
- 关闭状态向左滑动打开,已展开状态向右滑动关闭;点击内容区域默认关闭。
- 同一页面只保留一个激活项,打开新项时会自动关闭旧项。
- 超过操作面板总宽度后继续拖动会产生阻尼,释放后回到正常位置。
- 操作文字在按钮宽度不足时自动隐藏,避免换行和挤压。
- 超长列表建议配合 uni-app x 的
list-view/list-item使用。
兼容性与限制
- 适用于 uni-app x 标准组件模式,不适用于普通 uni-app Vue 项目。
- 支持 Android 5.0+、iOS 12+、Web(Safari/Chrome)和微信小程序。
- 建议使用 HBuilderX 4.31+ 与 uni-app x 4.31+。
- 页面级主动控制依赖有效的
index;未传index的组件仍可正常手势操作,但不会被索引 API 找到。 - 单个操作按钮最大宽度为
240px,操作面板总宽度最大为480px。 - 页面负责维护列表数据、业务操作和删除结果,组件只负责交互状态与事件通知。
常见问题
为什么页面事件参数要写成 any?
uni-app x 模板中的自定义组件事件可能被推断为 Any。如果直接把 $event 传给 UTSJSONObject 参数,可能出现“实际类型为 Any,预期类型为 UTSJSONObject”的编译错误。建议在页面事件函数中接收 any,再显式转换:
function onAction(index : number, event : any) : void {
const actionEvent = event as UTSJSONObject
const key = actionEvent.getString('key') ?? ''
}
删除后为什么不直接在 action 事件中移除数据?
开启 deleteAnimation 的按钮会在动画完成后触发 deleteAnimationEnd,页面应在该事件中移除数据,以免提前销毁组件而中断动画。
为什么主动控制没有效果?
请确认组件传入了有效的 :index="index",并且调用时使用的是当前渲染顺序对应的列表索引,而不是业务 id。
许可证
本插件免费使用,具体授权方式以插件市场页面说明为准。

收藏人数:
购买源码授权版(
试用
使用 HBuilderX 导入示例项目
赞赏(0)
下载 9
赞赏 0
下载 12443885
赞赏 1935
赞赏
京公网安备:11010802035340号