更新记录

1.0.0(2026-07-21)

首发版本。

  • 提供 uni-app x UTS 标准组件模式的右侧操作列表项。
  • 支持左滑展开、右滑关闭、方向锁定、速度判定和越界阻尼。
  • 支持多个操作按钮同步展开、按钮禁用和 right 插槽自定义操作区域。
  • 支持 actionopenclosechangetap 等交互事件。
  • 支持 modelValue / v-model 受控开合状态。
  • 支持页面级打开、关闭、切换、关闭激活项和获取激活索引。
  • 支持组件实例的 openclosetogglecloseActivegetActiveIndex 方法。
  • 支持删除淡出与高度收缩动画,并通过 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 } 删除动画完成。页面应在此时移除对应业务数据。

actiondeleteAnimationEndindex 是操作按钮在 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 后,组件会:

  1. 自动读取当前列表项的实际高度。
  2. 让内容淡出并平滑收缩行高。
  3. 在视觉动画完成后触发 deleteAnimationEnd
  4. 由页面在回调中删除业务数组中的对应数据。

组件不会自动修改页面的 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

许可证

本插件免费使用,具体授权方式以插件市场页面说明为准。

隐私、权限声明

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

无需系统权限。

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

组件不采集、不上传任何用户数据。

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

无广告、无广告 SDK、无引流内容。

暂无用户评论。