返回

拖动表格头:实现代码如何编写?

前端

实现拖动表格头功能的步骤:

  1. 准备 HTML 结构:
<table>
  <thead>
    <tr>
      <th data-field="name">姓名</th>
      <th data-field="age">年龄</th>
      <th data-field="city">城市</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>张三</td>
      <td>20</td>
      <td>北京</td>
    </tr>
    <tr>
      <td>李四</td>
      <td>25</td>
      <td>上海</td>
    </tr>
    <tr>
      <td>王五</td>
      <td>30</td>
      <td>广州</td>
    </tr>
  </tbody>
</table>
  1. 添加必需的 CSS 样式:
table {
  width: 100%;
  border-collapse: collapse;
}

th {
  padding: 5px 10px;
  text-align: center;
  cursor: pointer;
}

th.active {
  background-color: #ccc;
}

.drag-indicator {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 100%;
  background-color: #ccc;
  opacity: 0;
}
  1. 编写 JavaScript 代码:
// 获取表格元素
const table = document.querySelector('table');

// 获取表头元素
const headers = table.querySelectorAll('th');

// 为每个表头元素添加事件监听器
headers.forEach(header => {
  header.addEventListener('mousedown', startDrag);
});

// 开始拖动表头元素的函数
function startDrag(e) {
  // 获取被拖动的表头元素
  const header = e.target;

  // 获取被拖动的表头元素的字段名称
  const field = header.dataset.field;

  // 创建拖动指示器元素
  const dragIndicator = document.createElement('div');
  dragIndicator.classList.add('drag-indicator');

  // 将拖动指示器元素添加到表格中
  table.appendChild(dragIndicator);

  // 获取拖动指示器元素的宽度
  const dragIndicatorWidth = dragIndicator.offsetWidth;

  // 获取拖动指示器元素的高度
  const dragIndicatorHeight = dragIndicator.offsetHeight;

  // 获取被拖动的表头元素的宽度
  const headerWidth = header.offsetWidth;

  // 获取被拖动的表头元素的高度
  const headerHeight = header.offsetHeight;

  // 获取被拖动的表头元素的偏移量
  const headerOffset = header.getBoundingClientRect();

  // 获取表格的偏移量
  const tableOffset = table.getBoundingClientRect();

  // 计算拖动指示器元素的初始位置
  const dragIndicatorX = headerOffset.left - tableOffset.left + headerWidth;
  const dragIndicatorY = headerOffset.top - tableOffset.top + headerHeight;

  // 设置拖动指示器元素的初始位置
  dragIndicator.style.left = dragIndicatorX + 'px';
  dragIndicator.style.top = dragIndicatorY + 'px';

  // 设置拖动指示器元素的宽度
  dragIndicator.style.width = dragIndicatorWidth + 'px';

  // 设置拖动指示器元素的高度
  dragIndicator.style.height = dragIndicatorHeight + 'px';

  // 设置拖动指示器元素的透明度
  dragIndicator.style.opacity = 1;

  // 鼠标移动事件的监听器
  document.addEventListener('mousemove', drag);

  // 鼠标抬起事件的监听器
  document.addEventListener('mouseup', endDrag);

  // 拖动表头元素的函数
  function drag(e) {
    // 获取鼠标的当前位置
    const mouseX = e.clientX;
    const mouseY = e.clientY;

    // 计算拖动指示器元素的当前位置
    const dragIndicatorX = mouseX - tableOffset.left - dragIndicatorWidth / 2;
    const dragIndicatorY = mouseY - tableOffset.top - dragIndicatorHeight / 2;

    // 设置拖动指示器元素的当前位置
    dragIndicator.style.left = dragIndicatorX + 'px';
    dragIndicator.style.top = dragIndicatorY + 'px';

    // 获取所有表头元素
    const allHeaders = table.querySelectorAll('th');

    // 找到拖动指示器元素所在的表头元素
    let headerElement = null;
    for (let i = 0; i < allHeaders.length; i++) {
      const header = allHeaders[i];
      const headerOffset = header.getBoundingClientRect();
      if (dragIndicatorX + dragIndicatorWidth / 2 >= headerOffset.left && dragIndicatorX + dragIndicatorWidth / 2 <= headerOffset.right) {
        headerElement = header;
        break;
      }
    }

    // 如果拖动指示器元素所在的表头元素不是被拖动的表头元素,则交换两个表头元素的位置
    if (headerElement && headerElement !== header) {
      const headerField = header.dataset.field;
      header.dataset.field = headerElement.dataset.field;
      headerElement.dataset.field = headerField;

      const headerIndex = Array.from(headers).indexOf(header);
      const headerElementIndex = Array.from(headers).indexOf(headerElement);

      headers[headerIndex] = headerElement;
      headers[headerElementIndex] = header;

      // 重新渲染表格
      table.innerHTML = '';
      renderTable();
    }
  }

  // 结束拖动表头元素的函数
  function endDrag(e) {
    // 移除拖动指示器元素
    dragIndicator.parentNode.removeChild(dragIndicator);

    // 移除鼠标移动事件的监听器
    document.removeEventListener('mousemove', drag);

    // 移除鼠标抬起事件的监听器
    document.removeEventListener('mouseup', endDrag);
  }
}

// 渲染表格
function renderTable() {
  const tableBody = table.querySelector('tbody');

  // 获取所有数据行
  const rows = tableBody.querySelectorAll('tr');

  // 排序数据行
  rows.sort((a, b) => {
    const field = a.querySelector('th[data-field]').dataset.field;
    const aValue = a.querySelector(`td[data-field="${field}"]`).textContent;
    const bValue = b.querySelector(`td[data-field="${field}"]`).textContent;

    if (aValue < bValue) {
      return -1;
    } else if (aValue > bValue) {
      return 1;
    } else {
      return 0;
    }
  });

  // 将排序后的数据行添加到表格中
  for (let i = 0; i < rows.length; i++) {
    tableBody.appendChild(rows[i]);
  }
}

// 调用渲染表格函数
renderTable();

通过以上步骤,您就可以实现表格头拖动排序的功能。希望本指南对您有所帮助。