实现按钮拖拽插入表格功能时appendChild参数非Node错误如何解决
问题根因
你代码里的两个核心错误:
drop函数中document.getElementById(data).value取的是按钮的文本值(字符串类型),不是DOM节点,所以传给appendChild直接报错- 循环生成可拖拽div时写死了
id="dragbutton",会导致页面存在大量重复ID,document.getElementById只能取到第一个匹配的元素,拖拽功能会完全混乱
基础修复方案
第一步:修改按钮生成逻辑,保证ID唯一
@foreach (var t in ct.cases) { <!-- 用业务唯一ID作为元素id,避免重复 --> <div class="database-cases" data-tooltip="@t.Title" draggable="true" ondragstart="drag(event)" id="drag_@t.Id"> <input class="database-cases-id btn btn-link" type="button" value="@t.IdText" onclick="" /> <sub class="database-cases-title">@t.Title</sub> </div> }
第二步:修改JS拖拽逻辑
function allowDrop(event) { event.preventDefault(); } function drag(event) { event.dataTransfer.setData("text", event.target.id); } function drop(event) { event.preventDefault(); var dragElId = event.dataTransfer.getData("text"); // 直接获取拖拽的完整DOM节点,不要取value var dragElement = document.getElementById(dragElId); // 兼容表格DOM规范,避免直接把div插到table标签下导致布局异常 var dropTarget = event.target; if(dropTarget.tagName === 'TABLE') { // 拖到表格空白区域自动创建行和单元格 const newRow = dropTarget.insertRow(); const newCell = newRow.insertCell(); newCell.appendChild(dragElement); } else if (dropTarget.tagName === 'TD' || dropTarget.tagName === 'TH') { // 拖到已有单元格直接插入 dropTarget.appendChild(dragElement); } else { // 拖到表格内其他子元素时,自动向上找最近的单元格插入 const closestCell = dropTarget.closest('td, th'); if(closestCell) closestCell.appendChild(dragElement); } }
更优实现方案
- 如果需要保留右侧列表的原始按钮(复制而非剪切移动),可以在拖拽时存储节点的HTML字符串,drop阶段用
document.createRange().createContextualFragment(HTML字符串)把字符串转成DOM节点再插入即可,不用修改原始节点 - 拖拽逻辑复杂的话可以直接用SortableJS这类成熟的拖拽库,原生封装了节点移动、边界判断、多区域拖拽等能力,代码量可以减少80%以上
- 建议把行内的拖拽事件绑定改成JS统一监听,后续维护更方便
内容的提问来源于stack exchange,提问作者amxNico
相关产品推荐
相关产品推荐

