必须操作table.cache['your-id']数组并重渲染,禁用直接移动tr;交换用三步法并校验边界;data-index为当前页索引,需parseint();reload后需手动恢复选中、滚动、高亮状态;前端排序须同步更新服务端字段。
必须操作原始数据数组并重渲染,不能直接移动 tr 元素 —— 否则分页错乱、选中状态丢失、table.reload() 会覆盖你的 dom 改动。
用 table.cache 拿当前页数据并交换数组元素
不要依赖你初始化时传入的原始数组(比如 data: myData),Layui 内部会做副本处理。正确方式是读取 table.cache['your-id'],它返回当前页已渲染的数据副本(含分页后过滤结果)。
- 交换用经典三步法:
let temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;,别用splice链式调用,索引极易错位 - 上移:目标索引为
i,需与i-1交换;下移则与i+1交换 - 边界必须判断:
i === 0时禁止上移,i === arr.length - 1时禁止下移 - 如果开了分页,
data-index是当前页内索引(从 0 开始),不是全局序号
通过 data-index 获取点击行在当前页的真实位置
别用 $(this).closest('tr').index() —— 表格有固定表头、合计行、分页栏时,DOM 层级和视觉顺序不一致,index() 返回的是整个 tbody 中的物理位置,完全不可靠。
- 在列配置里写操作按钮:
{"title":"操作","toolbar":"#moveBar"} - 监听工具栏事件:
table.on('tool(your-id)', function(obj){...}) - 从
obj.tr.attr('data-index')取值(字符串),记得parseInt() - 这个值只对当前页有效;跨页移动需额外处理页码跳转逻辑
reload() 后状态丢失怎么恢复
table.reload() 是全量重绘,所有 UI 状态都会清空。这不是 bug,是设计使然 —— 但你可以手动补救。
- 多选状态:
table.checkStatus('your-id').data拿到当前页已勾选项,reload后遍历用table.checkRow()或给对应数据项加checked: true再触发一次勾选 - 滚动位置:保存
$('.layui-table-box').scrollTop(),reload的done回调里用setTimeout(() => {...}, 0)确保 DOM 更新完成后再设回去 - 单行高亮:不能只靠
addClass,得在done回调里重新查tr[data-index="X"]并加 class - 性能提醒:表格超 500 行时,频繁
reload会卡顿;此时应改用table.cache手动 patch 对应tr和td,避免整表重绘
最容易被忽略的是:你以为交换了 table.cache 就万事大吉,但如果你没同步更新服务端排序字段(比如数据库里的 sort_order),下次刷新页面或换页,顺序又回去了。前端重排只是临时态,最终必须落库。











