跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

HTML怎么做拖拽排序手势_html触摸拖拽排序手势实现【建议收藏】

移动端拖拽排序不能用 dragstart 是因 iOS Safari 和 Android Chrome 默认禁用其触摸触发,需手动用 touchstart/touchmove/touchend 模拟,并用 transform、防抖、数据驱动更新等方案保障流畅与状态正确。 触摸设备上 拖拽排序 为什么不能直接用
dragstart
? 因为移动端浏览器(尤其是 iOS Safari 和 Android Chrome)默认禁用
dragstart
/
drop
等原生拖放事件的触摸触发——这不是 bug,是规范行为。你绑了
ondragstart
,手指一按就毫无反应,控制台也不报错,纯静默失效。 必须绕过原生 drag API,改用
touchstart
→
touchmove
→
touchend
手动模拟拖拽逻辑。 禁用默认滚动:在
touchstart
里调用
event.preventDefault()
,否则手指一滑页面就滚走了 记录初始位置和目标元素索引:用
dataset.sortIndex
或数组下标存当前项原始位置 动态插入占位符(
  • )代替“被拖走”的视觉空缺,否则列表会突然塌陷 避免 touchmove 频繁重排:只在位移超过 10px 后才触发位置更新,防抖用
    requestAnimationFrame
    包一层更稳 如何让拖拽项跟着手指实时移动(不卡顿)? 关键不是绝对定位 + left/top,而是用
    transform: translate3d(x, y, 0)
    。iOS Safari 对 transform 的渲染走 GPU,比改 top/left 流畅得多,且不会触发 layout。 示例核心逻辑: 立即学习 “ 前端免费学习笔记(深入) ”; 使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件 如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Andr​​oid友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Andr​​oid应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更 下载
    let startY = 0; let startTop = 0; let isDragging = false;

    item.addEventListener('touchstart', e => { const touch = e.touches[0]; startY = touch.clientY; startTop = parseFloat(getComputedStyle(item).top) || 0; isDragging = true; item.style.transform = translate3d(0, 0, 0); item.style.transition = 'none'; e.preventDefault(); });

    document.addEventListener('touchmove', e => { if (!isDragging) return; const touch = e.touches[0]; const dy = touch.clientY - startY; item.style.transform = translate3d(0, ${startTop + dy}px, 0); e.preventDefault(); });

    document.addEventListener('touchend', () => { if (!isDragging) return; // 这里计算最终插入位置,更新数据数组,重渲染列表 isDragging = false; item.style.transform = ''; item.style.transition = ''; });

    排序后如何正确更新 DOM 并保持状态? 别直接
    appendChild()
    或
    insertBefore()
    移动真实 DOM 节点——这会导致 input 失焦、video 暂停、canvas 清空等副作用。真实项目里,拖拽只是“改顺序”,渲染应由框架或数据驱动重新生成。 维护一个有序的
    items
    数组,拖拽结束时只交换数组内两个元素(用 splice + index 计算) 用
    key
    (如
    data-key="item-123"
    )绑定每个项,确保 diff 时复用节点而非销毁重建 如果不用框架,手动重排需先 detach 所有子节点,再按新顺序 append,避免 layout thrashing 特别注意表单控件:拖拽中若某项含
    ,要提前保存其
    value
    和
    selectionStart
    ,重排后恢复 iOS 上 touchmove 有时不触发? 这是 iOS 15.4+ 的已知问题:当页面有
    overflow: scroll
    的父容器,且 touchstart 在该容器内触发时,后续 touchmove 可能被吞掉。根本原因是 Safari 的“scroll cancellation”机制误判为滚动意图。 解决办法只有两个有效: 给触发拖拽的容器加
    touch-action: none
    (但会禁用内部所有滚动,慎用) 更稳妥的是:检测到
    touchstart
    后立即在
    body
    上临时加
    touch-action: none
    ,
    touchend
    后立刻恢复为
    touch-action: auto
    不要依赖
    passive: false
    ,iOS 对 passive 选项处理不一致,
    preventDefault()
    才是唯一可靠拦截方式 真正麻烦的从来不是拖拽本身,而是拖拽过程中用户突然缩放、横竖屏切换、或者在列表里混用了可点击按钮——这些边界情况没做隔离,排序就会错乱或卡死。

    相关文章