您的位置:首页 > Web前端 > JavaScript

js表头固定实现思路汇总

2015-09-11 17:39 726 查看
表头固定,表身滚动的特效,被广泛运用于各种大数据量展示的页面,本人在实践开发过程中总结了3中实现方式,现在,分享给大家。

思路一

  当发生滚动事件后,动态复制一份表头,将其放置在原表头的位置,为滚动的容器添加scroll事件,时刻保持复制表头的top=滚动条的垂直位置($(obj).scrollTop())

以下为demo代码实现:

-CSS 实现

<style type="text/css">
.table {
width:240px;
}
.table tr >td,.table >thead>tr>th {
border:1px solid green;
width:50px;
}
.header-copy{
background:red;
}
#scrollContainer{
width:260px;
position:fixed;
height:200px;
overflow-y:auto;
}
</style


-HEML实现

<div id='scrollContainer'  >
<table class="table" cellspacing=0 cellpadding=0 id="mytab">
<thead >
<tr>
<th>姓名</th><th>爱好</th>
</tr>
</thead>
<tbody>
<tr>
<td>码妞一</td><td>吉他</td>
</tr>
</tbody>
</table>
</div>
<!-- 以下的js只是为了批量生成数据,真正固定表头的方法是fixTabHeader -->
<script type="text/javascript">
$(document).ready(function(){
var row=$("#mytab >tbody>tr:first");
for(i=0;i<30;i++){
$('table#mytab > tbody').append(row.clone());
}
fixTabHe
f870
ader("mytab","scrollContainer");
});
</script>


-JS实现

<script language="javascript" type="text/javascript" >
function fixTabHeader(tabid,scrollid){
// 获取滚动条容器
var scrollDiv =$("#"+scrollid);
// 将表格拷贝一份
var tb2 =$("#"+tabid).clone(true);
// 将拷贝得到的表格中非表头行删除
if(tb2.size()>0) {
tb2.find("tr:not(:first)").remove();
}
// 创建一个div ,并添加到滚动容器中
var bakDiv =$("<div style='position:absolute;display:none;width:100%;'></div>");
bakDiv.css("top",scrollDiv.scrollTop());
bakDiv.appendTo(scrollDiv);
// 将拷贝得到的表格在删除数据行后添加到创建的div中
tb2.addClass("header-copy");
tb2.appendTo(bakDiv);
scrollDiv.scroll(function(){
// 设置div的top值为滚动条距离滚动条容器顶部的距离值
bakDiv.css({top:$(this).scrollTop()+"px",background:"#e8eaeb",display:"block"});
});
}
</script>


分析

   以上实现的是基于某个父容器进行滚动的,如果有朋友想要实现基于浏览器进行滚动,只需要将fixTabHeader方法中scrollDiv 申明为当前文档对象就可以了,即scrollDiv=$(window).

  此种方法适合比较简单的表格,如果你的表格应用了很多外部样式,比如许多朋友为了效果好实用bootstrap框架做特效,这时候会发现该种方法实现的固头,会有表头的数据行和表内容无法对齐的现象,而且这个问题及其难调,本人花了好几天也没有搞定,如果有看文章的朋友解决了,欢迎和我交流。

思路二

  实现思路同上面的demo相似,都是复制一份表头来做固定,不同的是上面例子是复制了一份表头直接放置到滚动容器中固定,而本例子是将复制的表头放在了tbody中,然后做固定。位置不同。

css

table {
width:98%;
text-align:center;
color:blue
}
table .header{
background:green;
}
table .header-fixed {
position: fixed;
}
#scrollContainer{
height:200px;
overflow-y:auto;
}


<div id='scrollContainer'  >
<table class="table" cellspacing=0 cellpadding=0 id="mytable">
<thead class="header">
<tr>
<th>姓名</th><th>爱好</th>
</tr>
</thead>
<tbody>
<tr>
<td>一介码妞</td><td>吉他</td>
</tr>
</tbody>
</table>
</div>
<!-- 以下的js只是为了批量生成数据,真正固定表头的方法是fixTabHeader -->
<script type="text/javascript">
$(document).ready(function(){
var row=$("#mytable >tbody>tr:first");
for(i=0;i<80;i++){
$('table#mytable > tbody').append(row.clone());
}
$("#mytable").fixedHeader();
});
</script>


<script type="text/javascript">
(function () {
(function ($) {
return $.fn.fixedHeader = function (options) {
var config;
config = {
bgColor: '#ff82ab'
};
if (options) {
$.extend(config, options);
}
return this.each(function () {
var $head, $parent, headTop, isFixed, o, ww;
processScroll = function () {
var headTop, i, isFixed, scrollTop, t;
if (!o.is(':visible')) {
return;
}
i = void 0;
scrollTop = $parent.scrollTop();
t= $head.length && $head.offset().top;
if (!isFixed && headTop !== t) {
headTop = t;
}
if (scrollTop >= headTop && !isFixed) {
isFixed = 1;
} else {
if (scrollTop <= headTop && isFixed) {
isFixed = 0;
}
}
if (isFixed) {
return $('thead.header-copy', o).show();
} else {
return $('thead.header-copy', o).hide();
}
};
o = $(this);
$parent=$("#scrollContainer");//$($(this).parent());
$head = $('thead.header', o);
isFixed = 0;
headTop = ($head.length) && ($head.offset().top);
$parent.on('scroll',processScroll);
$head.on('click', function () {
if (!isFixed) {
return setTimeout(function () {
return $parent.scrollTop($head.scrollTop());
}, 10);
}
});
$head.clone().removeClass('header').addClass('header-copy header-fixed').appendTo(o);
ww = [];
o.find('thead.header > tr:first > th').each(function (i, h) {
return ww.push($(h).outerWidth(false));
});
$.each(ww, function (i, w) {
return o.find('thead.header > tr > th:eq(' + i + '), thead.header-copy > tr > th:eq(' + i + ')').css({ width: w });
});
o.find('thead.header-copy').css({
margin: '0 auto',
width: o.outerWidth(),
top:headTop-2,
'background-color': config.bgColor
});
return processScroll();
});
};
}(jQuery));
}.call(this));
</script>


分析

  demo1 和demo2的思路都是复制一份表头做固定。不同的是demo1有点粗糙直接放到了滚动容器中,做位置固定。而demo2是将它放到了自己table的tbody中。而且demo2还将表格固定的这个例子做成了一个比较通用的插件,方便在其他项目中通用。但是,令人遗憾的是,对于较复杂的例子,demo2也存在表头和表内容无法完全垂直的问题。而且不太好调试。

思路三

  写两个表格,一个为表头,另一个为表内容。当表内容数据量比较大时,可以直接在表内容所在的父容器进行滚动。以下为demo代码实现:



<table>
<thead class="header">
<tr>
<th>姓名</th><th>爱好</th>
</tr>
</thead>
</table>
<div id='scrollContainer' style="height:300px;overflow-y:auto;" >
<table class="table" cellspacing=0 cellpadding=0 id="mytable">
<tbody>
<tr>
<td>一介码妞</td><td>吉他</td>
</tr>
</tbody>
</table>
</div>
<!-- 以下的js只是为了批量生成数据,真正固定表头的方法是fixTabHeader -->
<script type="text/javascript">
$(document).ready(function(){
var row=$("#mytable >tbody>tr:first");
for(i=0;i<80;i++){
$('table#mytable > tbody').append(row.clone());
}
$("#mytable").fixedHeader();
});
</script>


<script type="text/javascript">
function fixTabHeaderScroll(tabid){
var $parent,$head,pTop,oTop,headTop,o;
o=$("#"+tabid);
oTop=o.height();
$parent=o.parent();
pTop=$parent.height();
$head=$parent.prev();
if (pTop <=oTop) {

$head.css({width:$head.outerWidth(true)-scrollBarWidth+"px"});

}else{
$head.css({width:100+"%"});
}
}
</script>


分析

  这种方式应该是最简单,最明了的实现方式,表头和表内容分家,各管各家,对于表头来说,不管表内容滚或者不滚,它都在哪里不离不弃。但是存在一个问题,在表内容没有滚动时,表头和表身是垂直对齐的,一旦表身出现滚动,新出现的滚动条会占用表身的部分宽度,这就导致表身和表头又不对齐。所以,我们需要在给两个表格应用同样样式的基础上,再用js函数控制两个的宽度,使他们宽度一致,大体思路是获取滚动条的宽,然后设置表头的宽度减去滚动条的宽度。

补充介绍Jquery的几个参数:

offsetWidth :当前对象的的宽度包括滚动条在内

scrollWidth :当前对象的滚动宽度不包括滚动条在内

在css的盒子模型中,最内部是content,然后是padding、border、margin

width=content

innerWidth = width + padding

outerWidth = innerWidth + border

outerWidth(true) = outerWidth + margin

关于outerWidth属性有一个传入参数可以控制它包不包含外部的margin 为true的话包含,默认不包含。

注意:要想表格相对于某个父容器做数据滚动,则该父容器必须做如下设置:

(1)设置固定高度,不设置高度或者用百分比设置高度,滚动不起作用

(2)设置属性overflow-y:auto

 必选项,否则当表格数据过多时,不会产生滚动条,而是自动延长该父容器的高度

(3)设置 position:relative,这个主要是针对前连个例子而言

 若不设置,拷贝得来的表头将相对于其设置该属性为该值的父节点(或间接父节点)定位,如果没有,则相对于body
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: