实现固定表头和表体拖动移动的过程,可以借助两个table元素来实现。其中一个table仅展示表头,另一个table则展示表体和滚动条。下面我们来详细讲解如何实现这个效果。
实现固定表头和表体拖动移动的过程,可以借助两个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实现固定表头拖动时仅限表体移动
- JavaScript webpack模块打包器如何优化前端性能 2022-10-21
- ajax和jsonp跨域的原理本质详解 2023-02-14
- 一款css实现的鼠标经过按钮的特效 2024-01-06
- css3与html5实现响应式导航菜单(导航栏)效果分享 2024-01-04
- Vue首页加载白屏原因以及10种解决方法汇总 2024-02-06
- 用html自己开发自己的串口TCP通讯调试软件 2023-10-26
- JavaScript获得url查询参数的方法 2023-12-01
- javascript 动态改变层的Z-INDEX的代码style.zIndex 2024-01-04
- 解决ajax传过来的值后台接收不到的问题 2023-02-15
- 如何使用JavaScript获取扫码枪扫码数据,执行相应的操作 2023-08-29