JavaScript表格行拖拽:如何将行插入到表格tbody末尾?
问题描述
我写的表格行拖拽脚本里,dropHandler函数目前总是把拖拽的行插入到目标行之前,这个功能正常,但我想加个判断:当拖拽的行被放到最后一行之后时,要把它插入到表格tbody的末尾,请问怎么实现?
原代码示例
JavaScript代码
/*** 表格行拖拽功能 */ function dragstartHandler(ev) { sourceRow = ev.target; sourceTableId = sourceRow.closest("table").id; } function dragoverHandler(ev) { ev.preventDefault(); } function dropHandler(ev) { ev.preventDefault(); targetRow = ev.target.closest("tr"); targetTable = targetRow.closest("table"); targetTableId = targetRow.closest("table").id; if (sourceTableId === targetTableId) { //console.log("正确的表格"); targetTableBody = targetRow.closest("tbody"); targetTableBody.insertBefore(sourceRow, targetRow); rebuildIndex(targetTableBody); //sourceRow.classList.remove("dragRow"); } else { console.log("错误的表格") } }
HTML代码
<table id="table2"> <thead> <tr> <th>标题1</th> <th>标题2</th> <th>标题3</th> <th>标题4</th> </tr> </thead> <tbody id="tableBody-table2"> <tr id="table2_row1" draggable="true" ondragstart="dragstartHandler(event)" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)"> <td>表格2数据1</td> <td>表格2数据2</td> <td>表格2数据3</td> <td>表格2数据4</td> </tr> <tr id="table2_row2" draggable="true" ondragstart="dragstartHandler(event)" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)"> <td>表格2数据5</td> <td>表格2数据6</td> <td>表格2数据7</td> <td>表格2数据8</td> </tr> <tr id="table2_row3" draggable="true" ondragstart="dragstartHandler(event)" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)"> <td>表格2数据8</td> <td>表格2数据9</td> <td>表格2数据10</td> <td>表格2数据11</td> </tr> </tbody> </table>
解决方案
实现这个需求,只需两步判断拖拽位置是否在最后一行之后:
- 获取tbody里的最后一行元素
- 结合拖拽事件的位置信息,判断当前放置点是否在最后一行的下方
修改后的dropHandler函数
function dropHandler(ev) { ev.preventDefault(); targetRow = ev.target.closest("tr"); targetTable = targetRow.closest("table"); targetTableId = targetRow.closest("table").id; if (sourceTableId === targetTableId) { targetTableBody = targetRow.closest("tbody"); const lastRow = targetTableBody.lastElementChild; // 获取目标行的位置坐标 const targetRect = targetRow.getBoundingClientRect(); // 判断是否拖到最后一行的下方 const isDroppedAfterLastRow = lastRow === targetRow && ev.clientY > targetRect.bottom; if (isDroppedAfterLastRow) { // 插入到tbody末尾 targetTableBody.appendChild(sourceRow); } else { // 插入到目标行之前 targetTableBody.insertBefore(sourceRow, targetRow); } rebuildIndex(targetTableBody); //sourceRow.classList.remove("dragRow"); } else { console.log("错误的表格") } }
逻辑说明
- 用
targetTableBody.lastElementChild获取tbody的最后一行 - 通过
getBoundingClientRect()拿到目标行的位置矩形,其中bottom是目标行底部的Y坐标 - 当目标行是最后一行,且鼠标Y坐标(
ev.clientY)大于目标行的bottom值时,判定为拖到了最后一行下方,此时用appendChild把行加到tbody末尾 - 其他情况保持原有插入逻辑
扩展:支持拖拽到tbody空白区域
如果希望拖拽到最后一行下方的tbody空白区域也能触发插入末尾,给tbody添加拖拽事件:
<tbody id="tableBody-table2" ondrop="dropHandler(event)" ondragover="dragoverHandler(event)">
然后修改dropHandler补充判断:
function dropHandler(ev) { ev.preventDefault(); targetRow = ev.target.closest("tr"); targetTable = ev.target.closest("table"); targetTableId = targetTable.id; if (sourceTableId === targetTableId) { targetTableBody = targetTable.querySelector("tbody"); if (!targetRow) { // 拖拽到tbody空白区域,直接插入末尾 targetTableBody.appendChild(sourceRow); } else { const lastRow = targetTableBody.lastElementChild; const targetRect = targetRow.getBoundingClientRect(); const isDroppedAfterLastRow = lastRow === targetRow && ev.clientY > targetRect.bottom; if (isDroppedAfterLastRow) { targetTableBody.appendChild(sourceRow); } else { targetTableBody.insertBefore(sourceRow, targetRow); } } rebuildIndex(targetTableBody); //sourceRow.classList.remove("dragRow"); } else { console.log("错误的表格") } }
内容的提问来源于stack exchange,提问作者Dirk
相关产品推荐
相关产品推荐

