js表头固定实现思路汇总

来源:互联网 发布:淘宝商城渔具店 编辑:程序博客网 时间:2024/05/16 18:33

表头固定,表身滚动的特效,被广泛运用于各种大数据量展示的页面,本人在实践开发过程中总结了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());     }    fixTabHeader("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
0 0