uni-swipe-action 从编辑页返回后滑动按钮仍显示的问题
一、问题描述
在 uni-app 二手车小程序首页,车辆列表使用了 uni-swipe-action 组件实现左滑展示「删除」和「编辑」按钮。用户操作流程如下:
- 左滑某条车辆,露出「删除」「编辑」按钮
- 点击「编辑」,跳转到编辑页面
- 保存成功,返回首页
Bug 表现:返回首页后,之前滑开的那条车辆仍然处于展开状态,「删除」「编辑」按钮依然可见,而不是像首次进入页面那样只显示列表本身。
期望行为:从编辑页返回首页时,应重置为初始状态,只看到车辆列表,看不到操作按钮。
二、原因分析
2.1 页面生命周期与状态保持
在 uni-app 中,使用 uni.navigateTo 跳转到编辑页时,首页并不会被销毁,而是被压入页面栈并进入「隐藏」状态。当用户从编辑页返回时,首页会触发 onShow,从隐藏恢复为显示。
问题在于:Vue 组件及其内部状态都被保留,包括 uni-swipe-action-item 的展开/收起状态。因此之前滑开的项会保持展开状态。
2.2 原有关闭逻辑的不足
原先的实现思路是:通过 ref 拿到每个 uni-swipe-action-item,调用其 close() 方法关闭:
const closeAllSwipeActions = () => {
if (swipeItems.value && swipeItems.value.length) {
swipeItems.value.forEach(item => {
if (item && typeof item.close === 'function') {
item.close()
}
})
}
}
但在 @dcloudio/uni-ui 的 swipe-action 实现中:
- 在微信小程序、H5 等平台,滑动状态由 wxs/renderjs 控制,内部使用
is_show状态 -
close()主要供部分非 H5/微信平台使用 -
官方推荐的关闭方式是调用父组件
uni-swipe-action的closeAll()方法,由父组件统一遍历子组件并设置vm.is_show = 'none'
因此,直接对子项调用 close() 在上述平台上可能无法正确关闭。
2.3 ref 使用方式的影响
原先把 ref="swipeItems" 写在 v-for 的 uni-swipe-action-item 上,Vue 3 中会得到子组件数组。不同平台下子组件的 API 不完全一致,直接遍历子项调用 close() 的可靠性和兼容性较差。
三、解决方案
3.1 使用父组件的 closeAll API
将 ref 放在父组件 uni-swipe-action 上,并调用其 closeAll() 方法:
<uni-swipe-action ref="swipeActionRef">
<uni-swipe-action-item
v-for="car in carList"
:key="car._id"
:right-options="getSwipeOptions(car)"
@click="onSwipeAction($event, car)"
>
<!-- 内容 -->
</uni-swipe-action-item>
</uni-swipe-action>
const swipeActionRef = ref(null)
const closeAllSwipeActions = () => {
const swipeAction = swipeActionRef.value
if (swipeAction && typeof swipeAction.closeAll === 'function') {
swipeAction.closeAll()
}
}
3.2 在 onShow 中配合 nextTick 调用
从编辑页返回时,onShow 会触发,但此时 DOM 可能尚未完全恢复。使用 nextTick 确保在下次 DOM 更新后再关闭:
onShow(() => {
nextTick(() => {
closeAllSwipeActions()
})
getCarList()
})
3.3 跳转前主动关闭(可选)
在点击「编辑」跳转前,也调用一次 closeAllSwipeActions(),避免带着展开状态离开页面,有利于状态更一致。
四、知识点小结
| 要点 | 说明 |
|---|---|
| 页面栈 |
navigateTo 跳转时原页面不销毁,返回时只是 onShow,组件状态保留 |
| uni-swipe-action 关闭 | 应通过父组件 uni-swipe-action 的 closeAll() 关闭,而非遍历子项调用 close()
|
| ref 使用 | 父组件统一管理子项状态时,优先对父组件加 ref,调用其对外 API |
| nextTick | 页面恢复显示时,用 nextTick 等 DOM 更新后再操作组件,避免时序问题 |
五、参考资料
- uni-swipe-action 插件文档
- uni-ui 源码:
node_modules/@dcloudio/uni-ui/lib/uni-swipe-action/uni-swipe-action.vue - uni-ui 源码:
node_modules/@dcloudio/uni-ui/lib/uni-swipe-action-item/mpwxs.js