下面是关于"HTML table鼠标拖拽排序功能"的完整攻略。
一、原理说明
在HTML表格中添加鼠标拖拽排序功能,本质上是通过监听鼠标在表格中的操作事件,动态调整表格中行或列的位置。
其中,主要的步骤可以分为以下几点:
- 监听鼠标操作事件,包括鼠标按下、鼠标移动、鼠标松开等事件;
- 在鼠标按下时,记录当前鼠标所在行或列的位置信息,包括其所在的表格、行或列号,以及点击时相对于其左上角的偏移量;
- 在鼠标移动时,根据鼠标当前的位置信息,计算出相对于按下时的偏移量,然后动态调整表格中行或列的位置;
- 在鼠标松开时,更新表格的行或列顺序,同时移除拖拽过程中添加的样式和事件监听。
二、示例说明
1. 示例一:拖拽排序表格行
下面是一个简单的示例,演示如何在HTML表格中添加拖拽排序表格行的功能。
<table>
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
<tr>
<td>小明</td>
<td>男</td>
<td>18</td>
</tr>
<tr>
<td>小红</td>
<td>女</td>
<td>20</td>
</tr>
<tr>
<td>小刚</td>
<td>男</td>
<td>22</td>
</tr>
</tbody>
</table>
实现步骤如下:
- 通过JavaScript代码,遍历表格中的每个行元素,设置鼠标按下、移动和松开事件监听器;
- 在鼠标按下时,记录当前行的信息,包括其当前的位置、所在的表格、行数和鼠标相对于其左上角的偏移量;
- 在鼠标移动时,更新当前拖拽行的位置,同时检测是否需要交换位置;
- 在鼠标松开时,更新表格的行顺序,同时移除拖拽过程中添加的样式和事件监听。
具体实现方式可以参考下面的代码示例:
// 获取表格元素
const table = document.querySelector('table');
// 获取所有行元素
const rows = table.querySelectorAll('tr');
// 记录拖拽行的信息
let dragRow = null;
let dragY = 0;
let targetRow = null;
// 遍历所有行元素
rows.forEach((row, index) => {
// 设置鼠标按下事件监听
row.addEventListener('mousedown', (event) => {
// 记录鼠标按下时的偏移量
dragY = event.clientY - row.getBoundingClientRect().top;
// 记录拖拽行的信息
dragRow = {
table: table,
rowNum: index,
top: row.getBoundingClientRect().top,
height: row.getBoundingClientRect().height,
y: event.clientY - row.getBoundingClientRect().top
};
// 添加样式
row.style.opacity = '0.5';
row.style.position = 'absolute';
row.style.top = dragRow.top + 'px';
row.style.left = row.getBoundingClientRect().left + 'px';
// 阻止事件冒泡
event.stopPropagation();
});
// 设置鼠标移动事件监听
row.addEventListener('mousemove', (event) => {
if (dragRow === null) return;
// 计算偏移量
const offset = event.clientY - dragRow.y - dragRow.top;
// 移动行
row.style.top = (dragRow.top + offset) + 'px';
// 计算目标行
targetRow = null;
rows.forEach((r, i) => {
if (i === dragRow.rowNum) return;
const top = r.getBoundingClientRect().top + r.getBoundingClientRect().height / 2;
if (event.clientY >= top) {
targetRow = {
table: table,
rowNum: i,
top: top,
height: r.getBoundingClientRect().height
};
}
});
});
// 设置鼠标松开事件监听
row.addEventListener('mouseup', (event) => {
if (dragRow === null) return;
if (targetRow !== null) {
// 交换位置
const target = rows[targetRow.rowNum];
target.parentNode.insertBefore(row, target);
target.parentNode.insertBefore(target, rows[dragRow.rowNum + 1]);
}
// 移除样式
row.style.opacity = '1';
row.style.position = '';
row.style.top = '';
row.style.left = '';
// 清除记录
dragRow = null;
targetRow = null;
});
// 设置鼠标松开事件监听
row.addEventListener('mouseleave', (event) => {
if (dragRow === null) return;
// 更新目标行为最后一行
targetRow = {
table: table,
rowNum: rows.length - 1,
top: rows[rows.length - 1].getBoundingClientRect().bottom,
height: rows[rows.length - 1].getBoundingClientRect().height
};
// 更新位置
row.style.top = (targetRow.top - row.getBoundingClientRect().height) + 'px';
});
});
2. 示例二:拖拽排序表格列
除了拖拽排序表格行,我们也可以通过类似的方式实现拖拽排序表格列的功能。下面是一个示例代码,演示如何实现该功能。
<table>
<thead>
<tr>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
</tr>
</thead>
<tbody>
<tr>
<td>小明</td>
<td>男</td>
<td>18</td>
</tr>
<tr>
<td>小红</td>
<td>女</td>
<td>20</td>
</tr>
<tr>
<td>小刚</td>
<td>男</td>
<td>22</td>
</tr>
</tbody>
</table>
实现步骤如下:
- 在表头中的每个列元素上添加鼠标按下、移动和松开事件监听器;
- 在鼠标按下时,记录当前列的信息,包括其当前的位置、所在的表格、列数和鼠标相对于其左上角的偏移量;
- 在鼠标移动时,更新当前拖拽列的位置,同时检测是否需要交换位置;
- 在鼠标松开时,更新表格的列顺序,同时移除拖拽过程中添加的样式和事件监听器。
具体实现方式可以参考下面的代码示例:
// 获取表格元素
const table = document.querySelector('table');
// 获取表头中每个列元素
const headers = table.querySelectorAll('thead th');
// 记录拖拽列的信息
let dragCol = null;
let dragX = 0;
let targetCol = null;
// 遍历所有列元素
headers.forEach((col, index) => {
// 设置鼠标按下事件监听
col.addEventListener('mousedown', (event) => {
// 记录鼠标按下时的偏移量
dragX = event.clientX - col.getBoundingClientRect().left;
// 记录拖拽列的信息
dragCol = {
table: table,
colNum: index,
left: col.getBoundingClientRect().left,
width: col.getBoundingClientRect().width,
x: event.clientX - col.getBoundingClientRect().left
};
// 添加样式
col.style.opacity = '0.5';
col.style.position = 'absolute';
col.style.left = dragCol.left + 'px';
col.style.top = col.getBoundingClientRect().top + 'px';
// 设置列宽度
table.querySelectorAll('col')[index].style.width = dragCol.width + 'px';
// 阻止事件冒泡
event.stopPropagation();
});
// 设置鼠标移动事件监听
col.addEventListener('mousemove', (event) => {
if (dragCol === null) return;
// 计算偏移量
const offset = event.clientX - dragCol.x - dragCol.left;
// 移动列
col.style.left = (dragCol.left + offset) + 'px';
// 计算目标列
targetCol = null;
headers.forEach((c, i) => {
if (i === dragCol.colNum) return;
const left = c.getBoundingClientRect().left + c.getBoundingClientRect().width / 2;
if (event.clientX >= left) {
targetCol = {
table: table,
colNum: i,
left: left,
width: c.getBoundingClientRect().width
};
}
});
});
// 设置鼠标松开事件监听
col.addEventListener('mouseup', (event) => {
if (dragCol === null) return;
if (targetCol !== null) {
// 交换位置
const target = headers[targetCol.colNum];
target.parentNode.insertBefore(col, target);
const cols = table.querySelectorAll('tr td:nth-child(' + (dragCol.colNum + 1) + ')');
cols.forEach((cell, index) => {
const target = target.parentNode.querySelectorAll('td:nth-child(' + (targetCol.colNum + 1) + ')')[index];
target.parentNode.insertBefore(cell, target);
});
table.querySelectorAll('col')[dragCol.colNum].style.width = targetCol.width + 'px';
table.querySelectorAll('col')[targetCol.colNum].style.width = dragCol.width + 'px';
}
// 移除样式
col.style.opacity = '1';
col.style.position = '';
col.style.left = '';
col.style.top = '';
// 清除记录
dragCol = null;
targetCol = null;
});
// 设置鼠标松开事件监听
col.addEventListener('mouseleave', (event) => {
if (dragCol === null) return;
// 更新目标列为最后一列
targetCol = {
table: table,
colNum: headers.length - 1,
left: headers[headers.length - 1].getBoundingClientRect().right,
width: headers[headers.length - 1].getBoundingClientRect().width
};
// 更新位置
col.style.left = targetCol.left - col.getBoundingClientRect().width + 'px';
});
});
三、总结
HTML table鼠标拖拽排序功能的实现有很多种方式,上面的示例只是其中的一种。在实际开发中,需结合实际情况进行应用。另外,在实现时,需要注意操作的流畅性和界面的美观度。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:HTML table鼠标拖拽排序功能 - Python技术站