HTML table鼠标拖拽排序功能

下面是关于"HTML table鼠标拖拽排序功能"的完整攻略。

一、原理说明

在HTML表格中添加鼠标拖拽排序功能,本质上是通过监听鼠标在表格中的操作事件,动态调整表格中行或列的位置。

其中,主要的步骤可以分为以下几点:

  1. 监听鼠标操作事件,包括鼠标按下、鼠标移动、鼠标松开等事件;
  2. 在鼠标按下时,记录当前鼠标所在行或列的位置信息,包括其所在的表格、行或列号,以及点击时相对于其左上角的偏移量;
  3. 在鼠标移动时,根据鼠标当前的位置信息,计算出相对于按下时的偏移量,然后动态调整表格中行或列的位置;
  4. 在鼠标松开时,更新表格的行或列顺序,同时移除拖拽过程中添加的样式和事件监听。

二、示例说明

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>

实现步骤如下:

  1. 通过JavaScript代码,遍历表格中的每个行元素,设置鼠标按下、移动和松开事件监听器;
  2. 在鼠标按下时,记录当前行的信息,包括其当前的位置、所在的表格、行数和鼠标相对于其左上角的偏移量;
  3. 在鼠标移动时,更新当前拖拽行的位置,同时检测是否需要交换位置;
  4. 在鼠标松开时,更新表格的行顺序,同时移除拖拽过程中添加的样式和事件监听。

具体实现方式可以参考下面的代码示例:

// 获取表格元素
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>

实现步骤如下:

  1. 在表头中的每个列元素上添加鼠标按下、移动和松开事件监听器;
  2. 在鼠标按下时,记录当前列的信息,包括其当前的位置、所在的表格、列数和鼠标相对于其左上角的偏移量;
  3. 在鼠标移动时,更新当前拖拽列的位置,同时检测是否需要交换位置;
  4. 在鼠标松开时,更新表格的列顺序,同时移除拖拽过程中添加的样式和事件监听器。

具体实现方式可以参考下面的代码示例:

// 获取表格元素
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技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • js+CSS实现弹出居中背景半透明div层的方法

    实现弹出居中背景半透明div层的方法基本思路是利用CSS实现半透明背景层,利用JavaScript控制弹框层的显示和隐藏并使其在页面居中。 1. 编写HTML结构 首先,在HTML中添加弹框层的结构,例如: <div id="mask"></div> <div id="dialog"&gt…

    css 2023年6月9日
    00
  • vue中关于@media媒体查询的使用

    当我们在使用 Vue 开发 Web 应用程序时,经常需要针对不同的屏幕尺寸进行布局和样式的调整。媒体查询(Media Queries)是一种很好的解决方案,它可以根据设备的屏幕尺寸自适应调整样式表的规则。在 Vue 中使用媒体查询也非常简单。 使用方式 在 Vue 中使用媒体查询,我们可以使用 @media 规则。这个规则可用于 CSS 样式表中,也可用于 …

    css 2023年6月10日
    00
  • 发挥火狐浏览器的广告拦截威力(图文教程)

    发挥火狐浏览器的广告拦截威力(图文教程) 广告拦截器是现代浏览器中常见的功能,能够帮助用户过滤广告和恶意网站,提高网页浏览的速度和安全性。本文将针对使用火狐浏览器的用户,介绍如何发挥火狐浏览器的广告拦截威力。 步骤一:启用火狐浏览器的广告拦截器功能 打开火狐浏览器,点击右上角的菜单按钮(三个横线)。 在下拉菜单中选择“选项(Options)”。 在弹出的“选…

    css 2023年6月11日
    00
  • JavaScript中获取高度和宽度函数总结

    下面是详细讲解“JavaScript中获取高度和宽度函数总结”的完整攻略: 获取元素的高度和宽度 获取元素的高度和宽度有多种方式,下面将介绍常用的四种方法。 1. offsetWidth 和 offsetHeight 属性 元素的 offsetWidth 和 offsetHeight 属性可以分别获取元素的宽度和高度,包括内边距、边框和滚动条(如果有)。 l…

    css 2023年6月10日
    00
  • CSS3实现各种图形的示例代码

    那我来给你详细讲解一下CSS3实现各种图形的示例代码的攻略。 准备工作 在开始实现各种图形之前,我们需要确保在HTML文件中引用了CSS文件,这里我们可以通过以下代码引入: <link rel="stylesheet" href="style.css"> 接着我们需要定义一些基础的CSS样式,比如背景色、字…

    css 2023年6月10日
    00
  • PC端和移动端自适应问题的快速解决方法

    针对PC端和移动端自适应问题的解决方法,我提供以下完整攻略: 1. 使用响应式设计 响应式设计是指利用media query查询技术来确保网站可在各种终端设备上正常显示,其核心原则就是使用相对单位(如%、em等)代替固定单位(如px),同时使用@media规则在不同的屏幕尺寸下(如768px、992px等)使用不同的样式效果。 在实践中,我们可以采用流式布局…

    css 2023年6月10日
    00
  • div+css布局必了解的列表元素ul ol li dl dt dd详解

    标题:Div+CSS布局必了解的列表元素ul ol li dl dt dd详解 正文: 列表元素在网页设计中非常常见,也是制作网页布局时不可或缺的元素。理解列表元素在网页设计中的应用,对于掌握Div+CSS布局设计技巧至关重要。本文将详细介绍列表元素ul、ol、li、dl、dt、dd的应用及使用技巧。 1. 无序列表ul和有序列表ol 无序列表ul和有序列表…

    css 2023年6月10日
    00
  • css样式加载顺序及覆盖顺序深入理解

    让我们来深入理解CSS样式加载顺序及覆盖顺序。 CSS样式加载顺序 在了解CSS样式加载顺序之前,需要知道的是,浏览器渲染页面时采用了一种“流”的工作模式,即从上到下加载解析页面的各种元素。当浏览器解析到CSS样式时,会按照一个特定的顺序加载这些样式,具体如下: 浏览器默认样式:浏览器会首先加载自己的默认样式,这类样式在所有CSS样式中权重最低。 用户样式表…

    css 2023年6月9日
    00
合作推广
合作推广
分享本页
返回顶部