uni-app中左滑删除不能直接用swiper,因其设计为整页轮播切换,不支持列表项级局部滑动;可靠方案是监听touch事件手动计算位移并实现弹性回弹,需注意跨端兼容、像素换算与事件拦截。
uni-app 里左滑删除为什么不能直接用 swiper?
因为 swiper 是为轮播设计的,它的滑动逻辑是「整页切换」,不支持单个列表项局部左滑呼出操作按钮(比如「删除」「标记」)。强行用它模拟,会出现手势冲突、回弹不准、无法响应点击等问题。
真正能稳定支撑左滑菜单的,只有两种方式:一是基于原生 scroll-view + 手动计算偏移(但仅限横向滚动容器,不适用于列表项级滑动),二是——更常用也更可靠的——监听 touchstart/touchmove/touchend 事件自己算位移。
-
scroll-view的scroll-x只控制整个容器横向滚动,不能给每个view单独加滑动行为 -
swiper的@change和current对应的是 swiper-item 索引,和列表项位置无关 - 微信小程序平台下,
movable-view虽然能拖,但不支持惯性、回弹、边界限制,体验差且 H5/APP 端不兼容
怎么用 touch 事件实现一个可回弹的左滑删除菜单?
核心思路是:在每个列表项外层套一层 view,监听它的触摸事件,根据 touches[0].clientX 差值动态更新 transform: translateX(),并在 touchend 时判断是否达到触发阈值(比如滑动超过 80px)。
关键点不是“滑多远”,而是“松手后怎么收”:要区分「轻滑回原位」和「重滑触发删除」,并加入弹性阻尼(比如超出边界时乘以 0.3 系数)防止生硬卡死。
- 必须在
data中保存startX和currentTranslateX,避免多次滑动叠加错乱 -
maxTranslateX不是固定值,得按菜单按钮宽度(如 120rpx)动态算,否则 iOS 上会滑过头或卡住 - 别忘了加
transition: transform 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94),原生ease回弹太慢 - H5 端要注意
event.touches在某些浏览器可能为空,得 fallback 到event.changedTouches
为什么滑动后点击失效或误触其他项?
这是最常被忽略的兼容性坑:微信小程序和 APP-NVUE 下,touchmove 默认会触发默认滚动行为,导致手指一动就触发了父级 scroll-view 滚动,子项的 touchend 根本收不到。
解决方法只有一条:在滑动过程中显式阻止冒泡和默认行为。
- 给滑动区域的
@touchmove绑定函数,并在函数末尾加event.preventDefault()和event.stopPropagation() - 如果用了
scroll-view包裹整个列表,记得设enable-flex="true"并禁用其内部滚动:scroll-y="false",否则 touch 事件会被截胡 - APP 端 NVUE 下,
touchstart的clientX值可能比 H5 小 20~30px,建议统一用pageX替代(需配合getSystemInfoSync().screenWidth做归一化)
如何让左滑菜单适配不同屏幕和字体缩放?
很多人写死 itemWidth: 80 或 threshold: 100,结果在 iPhone Plus 或开启系统大字体的安卓机上,菜单要么滑不动,要么一碰就删。根本原因是没把 rpx 转成真实 px 再参与计算。
uni-app 的 rpx 是逻辑单位,touch 事件返回的是物理像素(px),二者不能混用。正确做法是:先通过 uni.getSystemInfoSync().pixelRatio 换算,再结合 windowWidth 推导出 1rpx 对应多少 px。
- 例如:设菜单按钮宽
120rpx,当前设备pixelRatio=3,则实际 px 宽 =120 * 3 * (windowWidth / 750) - 阈值判断别用
> 100,改用> menuButtonWidth * 0.7,这样在小屏上更灵敏,大屏上更稳 - 字体缩放会影响
clientX坐标,但不会影响getBoundingClientRect(),必要时可用它取元素左偏移做校准
滑动菜单真正的难点不在“怎么动”,而在“什么时候停、停在哪、停稳没”。很多看似奇怪的抖动、卡顿、误删,其实都是松手瞬间的位移判定没处理好回弹曲线和平台差异。










