layui 原生 table 不支持拖拽排序,须用 sortable.js 或自写 drag/touch 事件;关键在同步 table.cache、调用 renderdata/reload 并处理服务端持久化。
layui 原生 table 模块不支持行或列的拖拽排序,必须手动集成第三方库(如 sortable.js)或自行监听 drag / touch 事件实现。直接改 cols 或加 sort: true 不起作用。
用 Sortable.js 实现行拖拽最省事
这是目前兼容性好、代码量少、与 layui 表格 DOM 结构贴合度最高的方案。关键不是“能不能拖”,而是“拖完数据有没有真变”。
- 必须在
table.render()的done回调里初始化 Sortable,否则tbody还没生成,Sortable.create()会报错 - 初始化时目标元素必须是
tbody[0](原生 DOM 节点),不能传 jQuery 对象或layui.table实例 -
onEnd回调里要操作table.cache['yourId']数组,按evt.oldIndex和evt.newIndex调整顺序,再调用table.renderData('yourId')刷新视图 - 别漏掉
filter: '.layui-table-empty',否则空数据提示行会被误拖,导致索引错乱
自己写 drag 事件要注意的坑
原生实现自由度高,但浏览器兼容性和状态同步极易出错。尤其移动端完全不可用 drag 系列事件,必须单独处理 touch。
-
dragstart中必须设e.dataTransfer.setData('text', 'dummy'),否则 Chrome/Firefox 不触发后续事件 -
dragover必须e.preventDefault(),否则默认行为会拦截 drop - 判断插入位置不能靠
$(e.target).index(),DOM 重排后 index 会漂移;应基于e.clientY和目标tr.getBoundingClientRect().top计算相对位置 - 移动端必须检测
'ontouchstart' in window,改用touchstart/touchmove/touchend,且touchmove里避免频繁调用getBoundingClientRect()
拖拽后数据没变?八成是这三处没对齐
拖拽视觉上动了,但导出、翻页、搜索还是老顺序——问题几乎都出在这三个地方没同步:
-
table.cache['id']是 layui 内部缓存的数据源,拖拽后必须手动调整这个数组顺序,不能只改 DOM -
table.reload('id', { data: newArr })才能真正刷新分页、搜索、导出逻辑;table.renderData()只刷新当前页视图 - 如果用了服务端分页(
url配置),table.cache仅存当前页数据,拖拽后需把新顺序发到后端持久化,否则刷新页面就回退
最麻烦的从来不是拖拽动画,而是 DOM、内存数组、服务端存储这三层状态的对齐时机。哪怕只漏掉一次 table.cache 更新,用户就会觉得“拖了等于没拖”。











