默认rowDrag配置不渲染拖拽预览,仅做DOM位置交换,导致无“影子”或视觉反馈;需用Sortable.js(配ghostClass等)或soulTable.preview模式实现占位符与高亮。
拖拽行时为什么看不到“影子”或预览效果
默认的 rowdrag 配置(包括 soultable 或原生扩展)不自动渲染拖拽预览,只做 dom 位置交换。你看到的“卡顿”“跳变”或“无反馈”,本质是浏览器没渲染临时视觉状态——它只是在 tbody 里快速移动 tr 元素,没有插入占位符、没有高亮目标区、也没有悬浮“影子行”。
用 Sortable.js 实现带预览的行拖拽(最稳方案)
直接复用 Layui 表格 DOM 结构 + Sortable,它原生支持 ghostClass、chosenClass 和 dragClass,能精准控制拖拽中各阶段样式:
- 确保已引入
Sortable.min.js(v1.15+),且 CSS 中定义了.sortable-ghost(透明占位)、.sortable-chosen(被拖行高亮) - 在
table.render().done回调里初始化,取到真实tbody元素:const tbody = document.querySelector('#demo-table tbody') - 启用
animation: 150让移动更平滑,避免“瞬移”感 - 关键:设置
handle: 'tr'或绑定到tr上,否则可能误触发表头/空行
示例片段:
done: function() {
const tbody = document.querySelector('#demo-table tbody');
new Sortable(tbody, {
animation: 150,
ghostClass: 'sortable-ghost',
chosenClass: 'sortable-chosen',
dragClass: 'sortable-drag',
handle: 'tr',
onEnd: function(evt) {
// 此处同步更新 data 数组,非仅 DOM
const tableIns = table.get('demo-table');
const data = [...tableIns.data];
const moved = data.splice(evt.oldIndex, 1)[0];
data.splice(evt.newIndex, 0, moved);
tableIns.data = data;
table.reload('demo-table', { data });
}
});
}
用 soulTable.slim.js 的 preview 模式(轻量但有约束)
soulTable 提供了内置预览能力,但需显式开启且依赖其 CSS:
- 必须加载
soulTable.css,否则.soul-table-drag-preview类无效 - 初始化时传入
preview: true:new LayuiTableDrag({ elem: 'demo-table', preview: true }) - 它会在目标行上方插入一个半透明
tr占位符,并高亮目标区域,但不支持自定义影子内容 - 注意:若表格启用了
fixed列,预览占位符可能错位——这是 fixed 列脱离文档流导致的,需额外 patch CSS 定位
自己画预览行?小心 tbody 重绘冲突
有人尝试在 mousemove 里手动 clone tr 并 append 到 body,再绝对定位跟随鼠标。这容易出问题:
- Layui 表格内部会频繁重绘
tbody(比如分页、搜索),你的 clone 节点可能被意外移除 - clone 出来的
tr若含lay-event或模板渲染内容,事件和数据绑定会丢失 - 移动端 touch 事件未适配,预览无法跟随手指
- 真正要做的不是“画预览”,而是让拖拽过程可感知:用 CSS 控制
opacity、transform: scale()、加 box-shadow 就足够传达状态
最常被忽略的一点:预览效果是否生效,80% 取决于 CSS 优先级。检查开发者工具里 .sortable-ghost 是否被其他样式覆盖,特别是 !important 声明或 inline style。











