layui原生table不支持拖拽排序,需用sortable.js等第三方方案;必须在done回调初始化,操作table.cache并调用renderdata或reloaddata同步状态,否则视觉拖拽无效。

Layui 原生 table 模块不支持行或列的拖拽排序,rowDrag: true 或 colDrag: true 这类参数是第三方插件(如 soulTable)提供的能力,直接写进 table.render() 里完全无效,控制台也不报错,只会静默失效。
为什么拖完一松手就回滚?
最常踩的坑是:只改了 <tbody> 里 <code><tr> 的 DOM 顺序,但没动 <code>table.cache['yourId'] 里的数组。Layui 所有后续行为——分页、搜索、导出、筛选、甚至 reload——全依赖这个缓存。它不变,视觉上拖了也等于白拖。
-
table.cache是 layui 内部唯一可信的数据源,必须用Array.splice()手动调整顺序 - 如果用了服务端分页(
url配置),table.cache只存当前页数据,跨页拖拽会失效;得先调table.getData()拿全量再操作 - 别在
drop回调里写table.reload("id", { data: [] }),这会覆盖你刚整理好的缓存,等于放弃所有调整
用 Sortable.js 实现行拖拽(推荐)
这是目前兼容性好、代码量少、与 layui 表格 DOM 结构贴合度最高的方案,但必须绕开两个关键时机坑:
- 必须在
table.render()的done回调里初始化Sortable.create(),确保tbody已真实渲染;传参必须是原生tbody[0],不能传 jQuery 对象 - 必须加
filter: '.layui-table-empty, .layui-table-total',否则空提示行、合计行会被误捕获,导致索引错乱 -
onEnd里要用evt.oldIndex和evt.newIndex操作table.cache['id']数组,再调table.renderData('id')或table.reloadData('id') - 禁用
ghostClass和chosenClass,layui 表格重绘时容易与这些样式冲突,引发视觉错位
自己写 drag/touch 事件要注意什么
自由度高,但浏览器兼容性和状态同步极易出错,尤其移动端完全不可用 drag 系列事件:
-
dragstart中必须设e.dataTransfer.setData('text', 'dummy'),否则 Chrome/Firefox 不触发后续事件 -
dragover和drop里必须e.preventDefault(),否则默认跳转或页面滚动会拦截 - 判断插入位置不能靠
$(e.target).index()—— DOM 重排后索引漂移;要用e.clientY+targetTr.getBoundingClientRect().top计算相对位置 - 移动端必须检测
'ontouchstart' in window,改用touchstart/touchmove/touchend+ CSS transform 模拟;touchstart里立刻e.preventDefault(),否则 iOS 会触发页面滚动打断拖拽
真正麻烦的从来不是拖拽动画,而是 DOM、table.cache、服务端存储这三层状态的对齐时机。哪怕只漏掉一次缓存更新,用户就会觉得“拖了等于没拖”。











