必须配合 touchstart 记录起始 clientx 和 touchmove 实时计算 deltax,仅当 math.abs(deltax) > 10 时才响应滑动,避免 touchend 单独触发导致误删。

直接用 touchstart/touchmove/touchend 手动算位移,别信“加个 swipe 事件就行”这种说法——原生 HTML 没这玩意,硬套库反而容易在 iOS Safari 上失灵。
为什么不能只监听 touchend 就触发删除
手指松开那一刻的位置,根本不能代表滑动意图。用户可能只是点一下、长按、或者中途抬手又放回,touchend 单独用会误判成“左滑”,导致点个按钮手一歪就删了。
- 必须配合
touchstart记录起始clientX -
touchmove中实时计算deltaX = currentX - startX,只响应Math.abs(deltaX) > 10的移动(过滤抖动) -
touchend时才看最终deltaX是否,且全程未中断(即没触发 <code>touchcancel) - 漏掉
touchcancel监听,手指划出元素边界后松手,状态就卡死
transform: translateX() 动画卡顿的真正原因
iOS Safari 对频繁 JS 修改 style.transform 极其敏感,每帧都重排重绘,不是“性能差”,是浏览器根本没把它当动画处理。
- 别在
touchmove里反复写el.style.transform = `translateX(${x}px)` - 改用
classList.toggle('swiped'),把位移逻辑全交给 CSS:.swiped { transform: translateX(-80px); } - 给滑动容器加
will-change: transform或transform: translateZ(0),提前触发硬件加速 -
transition必须写在非动态类上(比如写在.item-wrapper基础样式里),否则首次滑动无过渡
DOM 结构不隔离,滑动就露馅
如果直接对整个 <li> 做 translateX,删除按钮也会跟着跑,根本露不出来——这不是动画问题,是结构没分层。
- 必须嵌套两层:
<div class="item-wrapper"> 包内容,<code><div class="delete-btn"> 绝对定位在右侧<li> <code>.item-wrapper设position: relative,.delete-btn设position: absolute; right: 0; width: 80px; - 父容器
<li class="swipe-item">要加overflow: hidden,否则按钮滑出后仍能点到 - 子元素(如
<a></a>、<button></button>)在滑动中要临时禁用交互:touchstart 时加swiping类,CSS 里写.swiping * { pointer-events: none; }
最易被忽略的是 touchcancel 处理和 pointer-events 临时禁用——前者让滑出区域的手势不卡死状态,后者防止松手瞬间误触内部按钮。这两个点不补上,用户实际用起来永远觉得“有时候灵有时候不灵”。











