两个table实现固定表头拖动时仅限表体移动

yizhihongxing

实现固定表头和表体拖动移动的过程,可以借助两个table元素来实现。其中一个table仅展示表头,另一个table则展示表体和滚动条。下面我们来详细讲解如何实现这个效果。

步骤1:创建HTML结构

首先,我们需要创建两个table元素,并将它们的CSS样式设置为垂直排列,如下所示:

<div class="table-container">
  <table class="header-table">
    <thead>
      下面是表头
    </thead>
  </table>
  <table class="body-table">
    <tbody>
      下面是表体内容
    </tbody>
  </table>
</div>

同时,我们需要将这个容器的CSS样式设置为position: relative,以便我们后面使用绝对定位时,相对于这个容器定位。在此基础上,我们需要设置表头的CSS样式,使其具有固定位置,并能随着表体的滚动而保持在页面顶部。

.header-table {
  position: fixed;
  top: 0;
  display: none;
  /* 宽度必须与body-table的宽度一致 */
}

接下来的关键步骤是如何实现鼠标拖动时,仅限表体移动而表头不动。

步骤2:监听鼠标滚动事件

我们可以为表体的scroll事件添加一个监听器,以便在用户拖动时调整表头的位置。具体实现方式如下:

const bodyTable = document.querySelector('.body-table');
const headerTable = document.querySelector('.header-table');

bodyTable.addEventListener('scroll', () => {
  headerTable.style.left = -bodyTable.scrollLeft + 'px';
});

这个代码片段只有三行,但它实现了整个表的鼠标滚动事件的监听,并根据滚动条的位置,动态调整头部的位置。

步骤3:移动表格

接下来,我们需要实现鼠标拖拽时移动表格的逻辑。为了达到这个目标,我们可以在表格中添加一个包装层元素,使用绝对定位等方式来实现。

<div class="table-container">
  <div class="table-wrapper">
    <table class="header-table">
      <thead>
        下面是表头
      </thead>
    </table>
    <table class="body-table">
      <tbody>
        下面是表体内容
      </tbody>
    </table>
  </div>
</div>
.table-wrapper {
  position: absolute;
  top: 0;
  left: 0;
}

接着,我们需要在JavaScript中添加事件监听器,在鼠标按下后,开始移动表格。假设我们要从容器中移动表格,代码如下:

const tableContainer = document.querySelector('.table-container');

let isDragging = false;
let startX = 0;
let startY = 0;
let initialX = 0;
let initialY = 0;

tableContainer.addEventListener('mousedown', (e) => {
  isDragging = true;

  startX = e.pageX - initialX;
  startY = e.pageY - initialY;
});

tableContainer.addEventListener('mousemove', (e) => {
  if (isDragging) {
    initialX = e.pageX - startX;
    initialY = e.pageY - startY;

    tableContainer.style.left = initialX + 'px';
    tableContainer.style.top = initialY + 'px';
  }
});

tableContainer.addEventListener('mouseup', () => {
  isDragging = false;
});

通过这段代码,我们可以在mousedown事件中开始监听表格移动,当mousemove事件发生时,更新表格的位置,然后在mouseup事件中,完成移动操作。

示例

下面是一个示例如何使用上述方法来实现固定表头和表体,动态调整位置,以及拖动表格:

示例1

假设我们有一个包含20行数据的表格。我们可以使用上面提到的解决方案来实现固定表头和表体,以及表格的拖拽:

.table-container {
  position: relative;
}

.header-table {
  position: fixed;
  top: 0;
  display: none;
  /* 宽度必须与body-table的宽度一致 */
  width: 80%;
}

.body-table {
  width: 80%;
  /* 让table-container的padding-top值等于表头的高度 */
  margin-top: 50px;
  /* 让table-container的padding-right值等于滚动条的宽度 */
  margin-right: 15px; //需要自己设置一下滚动条的宽度,根据自己的实际情况
  /* 让滚动条保持一直存在 */
  overflow-y: scroll;
  height: 200px; //设置高度后会出现滚动条
}

.table-wrapper {
  position: absolute;
  top: 0;
  left: 0;
}

.table-container .no-data {
  height: 240px;
  line-height: 240px;
  text-align: center;
  margin: 0 auto;
}

.table-wrapper,
.header-table,
.body-table {
  width: 100%;
}

header, 
tr {
  display: table;
  width: 100%;        
  table-layout: fixed;
}

th, 
td {
  width: auto;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

body {
  margin: 0;
  padding: 0;
}

const tableContainer = document.querySelector('.table-container');
const bodyTable = tableContainer.querySelector('.body-table');
const headerTable = tableContainer.querySelector('.header-table');

bodyTable.addEventListener('scroll', () => {
  headerTable.style.left = -bodyTable.scrollLeft + 'px';
});

let isDragging = false;
let startX = 0;
let startY = 0;
let initialX = 0;
let initialY = 0;

tableContainer.addEventListener('mousedown', (e) => {
  isDragging = true;

  startX = e.pageX - initialX;
  startY = e.pageY - initialY;
});

tableContainer.addEventListener('mousemove', (e) => {
  if (isDragging) {
    initialX = e.pageX - startX;
    initialY = e.pageY - startY;

    tableContainer.style.left = initialX + 'px';
    tableContainer.style.top = initialY + 'px';
  }
});

tableContainer.addEventListener('mouseup', () => {
  isDragging = false;
});

示例2

下面是一个更为复杂的表格数据示例,例如一个销售报表,该表格中包含了许多统计数据,以及各种字段:

<div class="table-container">
  <div class="table-wrapper">
    <table class="header-table">
      <thead>
        <tr>
          <th rowspan="3">序号</th>
          <th rowspan="3" style="width: 120px">部门</th>
          <th rowspan="3">业务员</th>
          <th colspan="3">10月</th>
          <th colspan="3">11月</th>
          <th colspan="3">12月</th>
          <th colspan="3">全年</th>
        </tr>
                                             ···
      </thead>
    </table>
    <table class="body-table">
      <tbody>
        <tr>
          <td rowspan="14" width="80">1</td>
          <td rowspan="14" width="120">销售部</td>
          <td>张三</td>
          <td>12,000</td>
          <td>20,000</td>
          <td>3,000</td>
          <td>14,000</td>
          <td>20,000</td>
          <td>2,000</td>
          <td>16,000</td>
          <td>40,000</td>
          <td>25,000</td>
          <td>4,000</td>
          <td>69,000</td>
          ···
        </tr>
        ···
      </tbody>
    </table>
  </div>
</div>
.table-container {
  position: relative;
}

.header-table {
  position: fixed;
  top: 0;
  display: none;
  /* 宽度必须与body-table的宽度一致 */
  width: 80%;
}

.body-table {
  width: 80%;
  /* 让table-container的padding-top值等于表头的高度 */
  margin-top: 50px;
  /* 让table-container的padding-right值等于滚动条的宽度 */
  margin-right: 15px; //需要自己设置一下滚动条的宽度,根据自己的实际情况
  /* 让滚动条保持一直存在 */
  overflow-y: scroll;
  height: 400px; //设置高度后会出现滚动条
}

.table-wrapper {
  position: absolute;
  top: 0;
  left: 0;
}

.table-container .no-data {
  height: 440px;
  line-height: 440px;
  text-align: center;
  margin: 0 auto;
}

.table-wrapper,
.header-table,
.body-table {
  width: 100%;
}

header, 
tr {
  display: table;
  width: 100%;        
  table-layout: fixed;
}

th, 
td {
  width: auto;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

body {
  margin: 0;
  padding: 0;
}

const tableContainer = document.querySelector('.table-container');
const bodyTable = tableContainer.querySelector('.body-table');
const headerTable = tableContainer.querySelector('.header-table');

bodyTable.addEventListener('scroll', () => {
  headerTable.style.left = -bodyTable.scrollLeft + 'px';
});

let isDragging = false;
let startX = 0;
let startY = 0;
let initialX = 0;
let initialY = 0;

tableContainer.addEventListener('mousedown', (e) => {
  isDragging = true;

  startX = e.pageX - initialX;
  startY = e.pageY - initialY;
});

tableContainer.addEventListener('mousemove', (e) => {
  if (isDragging) {
    initialX = e.pageX - startX;
    initialY = e.pageY - startY;

    tableContainer.style.left = initialX + 'px';
    tableContainer.style.top = initialY + 'px';
  }
});

tableContainer.addEventListener('mouseup', () => {
  isDragging = false;
});

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:两个table实现固定表头拖动时仅限表体移动 - Python技术站

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

相关文章

  • vue实现下拉菜单效果

    以下是基于Vue实现下拉菜单效果的完整攻略,其中包含两个示例说明: 步骤1:创建Vue实例 首先,我们需要使用Vue框架来实现下拉菜单的效果。因此,我们需要在页面中引入Vue.js,然后创建一个Vue实例。具体代码如下: <!doctype html> <html> <head> <title>Vue下拉菜单示…

    css 2023年6月10日
    00
  • html内容超出了div的宽度如何换行让内容自动换行

    当HTML内容超出div的宽度时,可以通过设置CSS属性来让内容自动换行并显示在多个行内。下面是具体的攻略: 1. 设置CSS white-space属性 将white-space属性的值设置为“normal”或“pre-wrap”即可让内容自动换行: div{ white-space: normal; /*或者pre-wrap*/ } 其中,“normal…

    css 2023年6月10日
    00
  • nuxt 路由、过渡特效、中间件的实现代码

    接下来我将详细讲解Nuxt路由、过渡特效、中间件等实现代码的攻略。 Nuxt路由的实现代码 在Nuxt中,路由的实现采用的是Vue Router。Nuxt提供了一些配置选项帮助我们轻松地建立路由: 在 nuxt.config.js 文件中配置 router 选项,nuxt将自动生成路由。比如: javascript export default { rout…

    css 2023年6月10日
    00
  • 编写跨浏览器兼容的 CSS 代码

    编写跨浏览器兼容的 CSS 代码可以帮助我们在不同的浏览器中呈现出一致的样式效果,同时避免一些不必要的错误和问题。下面是我提供的编写跨浏览器兼容的 CSS 代码的完整攻略: 1. 确定目标浏览器 在编写跨浏览器兼容的 CSS 的时候,首先需要确定目标浏览器。为了让样式在大多数浏览器中都呈现出一致的效果,建议我们优先考虑主流浏览器,比如 Chrome、Fire…

    css 2023年6月9日
    00
  • 三种带箭头提示框总结实例

    针对“三种带箭头提示框总结实例”的攻略,我将从以下几点进行详细讲解: 三种带箭头提示框的分类介绍 三种带箭头提示框的使用方式 实例说明 1. 三种带箭头提示框的分类介绍 在网页设计中,我们常常需要使用提示框来引导用户关注某一重要信息。而三种带箭头提示框分别为: 左侧提示框 上方提示框 右上角提示框 它们的主要特点分别为: 左侧提示框:提示框呈垂直布局,箭头出…

    css 2023年6月11日
    00
  • css box-shadow实现曲边阴影与翘边阴影

    CSS的box-shadow属性可以用于为框添加阴影效果。阴影可以是内部阴影或外部阴影,可以是普通阴影或曲边阴影、翘边阴影等特殊形状。本文将为您提供实现CSS曲边阴影与翘边阴影的完整攻略。 实现CSS曲边阴影 在实现CSS曲边阴影效果之前,首先需要为框使用圆角(border-radius)来实现曲边。接下来使用box-shadow属性来添加阴影效果。 以下是…

    css 2023年6月9日
    00
  • 详解webpack4.x之搭建前端开发环境

    详解Webpack 4.x之搭建前端开发环境 简介 Webpack 是一个模块打包工具,它可以把多个模块打包成一个文件并且可以自动解决依赖关系。Webpack4.x 版本相对于之前版本进行了优化和改进。 本文将详细讲解使用 Webpack 4.x 搭建前端开发环境的完整攻略。 步骤 第一步:安装Node.js Webpack 是基于 Node.js 开发的,…

    css 2023年6月9日
    00
  • CSS布局中如何组织样式表以便于简化、维护

    在设计网站布局时,良好的CSS组织结构可以让代码更容易维护和更新。以下是一些在CSS中组织样式表以便于简化、维护的攻略: 1. 使用命名约定 一种常见的CSS命名约定是BEM,即块(Block)、元素(Element)和修饰符(Modifier)。通过使用BEM约定,可以使CSS规则更加易于理解和修改。例如: /* 块 */ .navbar {} /* 元素…

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