加 draggable="true" 仍拖不动,因浏览器对拖拽支持弱,默认当文件下载处理;须在dragover中e.preventDefault()、dragstart中setData传ID、避免给table设draggable。

原生拖拽表格行能用,但只加 draggable="true" 一定失败——缺事件拦截、不阻止默认行为、不传数据,三者任一缺失都会卡在“拖不动”或“松手没反应”。
为什么加了 draggable="true" 还是拖不动
浏览器对 <tr> 的拖拽支持极弱:它默认把拖拽当文件下载处理,<code>drop 事件被静默拦截。关键不是“能拖”,而是“允许放”。
- 必须在
dragover回调里调用e.preventDefault(),否则drop永远不会触发 -
dragstart中必须调用e.dataTransfer.setData('text/plain', id),否则目标端收不到原始行标识 - 别给
<table> 或 <code><tbody> 设 <code>draggable="true",会拖整个容器,失去行级控制 - Safari 要求
setData至少传空字符串,不设就直接拒绝拖拽 - 在
dragover中计算event.clientY相对于目标<tr> 的位置:<code>const rect = targetTr.getBoundingClientRect(); const isTopHalf = event.clientY <li>松手时,若鼠标在上半区,执行 <code>targetTr.before(draggedTr);下半区则用targetTr.after(draggedTr) - IE11 不支持
before/after,需降级为targetTr.parentNode.insertBefore(draggedTr, isTopHalf ? targetTr : targetTr.nextSibling) - 绝对不要重写
<tbody>.innerHTML,会清空所有 <code><input>的当前值和绑定的事件监听器拖拽过程中如何显示插入线提示
仅靠
:hover不行——拖拽时鼠标常悬停在空白处,hover 不触发。必须靠dragover动态计算并实时加样式。立即学习“前端免费学习笔记(深入)”;
- 在
dragover里根据上/下半区判断,给目标<tr> 加临时类,例如 <code>tr.insert-before或tr.insert-after - CSS 用
border-top: 2px dashed #007bff(插上方)或border-bottom: 2px dashed #007bff(插下方),避开outline和box-shadow,它们在border-collapse: collapse下会错位 - 每次新
dragover触发前,先清除之前所有insert-*类,再给当前目标加,避免残留 - 移动端原生 drag/drop 不可用,这类逻辑必须用
SortableJS或 touch 事件模拟替代
最容易被忽略的是数据同步:DOM 行序变了,但 JS 数组还按老顺序存着。如果表格绑定了表单输入或用于后续提交,不手动更新数组索引,后端收到的就是错乱顺序。纯 DOM 场景下,这个脱节问题往往拖到提交时才暴露。
- 在
drop 时怎么安全插入到目标行上方或下方
直接用 insertBefore 或 appendChild 容易错位:比如把 A 插到 B 下方,B 若已被移走,A 就插空了。最稳的是用 before() / after() 配合鼠标 Y 坐标判断方向。



















