Layui原生table不支持左右拖拽行顺序,仅支持上下拖拽;左右拖拽无语义且浏览器不触发有效drop判断,真实需求是上下行序调整+列头顺序调整。Layui 原生 `
table` 不支持“鼠标左右拖拽”改变行顺序——它只响应上下方向的拖拽(即 vertical reorder),**左右拖拽(horizontal drag)在表格行上无语义,浏览器也不触发有效 drop 区域判断**。你看到的“类似 Excel”的拖拽感,其实是视觉错觉:Excel 表格支持列宽拖拽、列顺序拖拽、行高拖拽,但「行数据左右拖拽」本身不存在;真实需求通常是「上下拖拽行调整顺序」+「列头左右拖拽调整显示顺序」。下面直奔实操重点:浏览器对 `tr` 元素的 `dragover` 事件只在垂直方向有稳定触发逻辑。当你横向移动鼠标时,`e.clienty` 变化微弱,`getboundingclientrect().top` 对比失效,插入位置极易误判为“同一行内”,导致 dom 顺序混乱或卡死。layui 渲染后 `tbody` 是块级流式布局,没有 `display: flex` 或 `grid` 的横向坐标锚点,强行做 left/right 判断等于在猜。
这是目前最稳定、兼容性最好、移动端也能 fallback 的方案。关键不是“怎么拖”,而是“拖完怎么同步数据”。
table.render()` 的 `done` 回调执行完毕再初始化拖拽,否则 `tbody` 还没挂载到 DOMSortable.create(tbody, { ... })`,不要选 `table.elem` —— `table.elem` 是 `div.layui-table` 容器,不是真正的 `tbody`onEnd` 里别直接操作 `table.cache`,要按 `tr` 顺序提取 `data-index` 或你存的唯一 ID 字段,重排原始数据数组table.reload('demo', { data: newArr })`,而不是 `table.reloadData()` —— 后者不重置分页状态,翻页后顺序就乱了iOS Safari 和安卓 Chrome 完全不触发 `dragstart/dragover/drop`。你写的 `draggable="true"` 在手机上等于没写。
'ontouchstart' in window`,走 `touchstart/touchmove/touchend` 流程touchstart` 里立刻 `e.preventDefault()`,否则 iOS 会抢走事件并滚动页面touchmove` 中用 `e.touches[0].clientY` 算位置,缓存 `tr.getBoundingClientRect()` 结果,别每帧都算DOM 动了,`table.config.data` 没动,`table.cache` 仍是旧顺序——导出、搜索、分页全部错乱。这不是 bug,是你漏了关键一步。
tbody tr`,读取每个 `tr` 上的 `data-index` 属性(渲染时由 Layui 自动写入)newArr = dataIndexList.map(i => originData[i])`table.reload()` 的 `data` 参数是完整新数组,不是部分 splice 或对象引用table.cache['demo']` 直接赋值——reload 会覆盖它,且 `initSort`、`page` 等状态不会自动更新preventDefault()`,少一次 `reload`,或者把 `data-index` 当成 `index()` 用,整个排序就“看起来动了,其实没变”。