html表格固定首行首列

html表格固定首行首列,适用于标准表格,格式如下:

<div>
    <table>
        <tbody>
            <tr>
                <th></th>
            </tr>
            <tr>
                <td></td>
            </tr>
        </tbody>
    </table>
</div>

写了两个方法:

1,表格表头固定,这种方法是copy一个table操作,不会改变原table任何样式,但是不支持原table上面的vue事件

2,对table的tr,th,td处理,过程比上面的方法要复杂,会改变原table的一些样式,table上的事件可以继续调用

在线demo:https://nbin2008.github.io/demo/tableFixHead/index.html

调用:

tableFixHead2({ tableArr: ['tableId'] });

需要注意的是:如果是SPA页面,路由跳转,需要在跳转前手动解绑resize事件

$(window).off('resize.tableId');
$(window).off('resize.null');

方法:

//表格表头固定,这种方法是copy一个table操作,不会改变原table任何样式,但是不支持原table上面的vue事件
tableFixHead({tableArr=[],type=null}) {
    //默认是固定头部和第一列,可传参数type=head只固定头部
    let go = function() {
        tableArr.forEach((id) => {
            let $table = $(`#${id}`),
                $cloneTable = $table.clone(true),
                $parent = $table.parent();
            $parent.find('.cloneTable').remove();
            $cloneTable.removeAttr('id').addClass('cloneTable');
            $parent.append( $cloneTable );
            $parent.scrollLeft(0);
            $parent.scrollTop(0);
            //
            $cloneTable.css({
                'border-width': 0,
            });
            //
            let $thOld = $table.find('th'),
                $th = $cloneTable.find('th'),
                $tr = $cloneTable.find('tr'),
                $thFirst = $th.eq(0),
                widthF = $thFirst.outerWidth() + 1, //这是第一列的宽度
                heightF = $thFirst.outerHeight();
            //tr固定宽高,第一行取自身的,其二行起取第一列的宽度
            $tr.each(function(i,v){
                if (i==0) {
                    $(v).css({
                        width: $(v).outerWidth() + 1,
                        height: heightF,
                        left: 0,
                        top: 0,
                    });
                } else {
                    $(v).css({
                        width: widthF,
                        height: heightF,
                        left: 0,
                        top: heightF*i,
                    });
                }
            });
            //th
            $th.each(function(i,v){
                $(v).css({
                    width: $thOld.eq(i).outerWidth()+1,
                    left: $thOld.eq(i).position().left,
                    top: 0,
                })
            });
            //td,因为最终只会保留第一列的td,所以可以设置固定的宽度,这个宽度是th第一个的
            $cloneTable.find('td').each(function(i,v){
                $(v).css({
                    width: widthF,
                })
            });
            $thFirst.css({
                'z-index': 2,
                'background-color': $tr.eq(0).css('background-color'),
            })
            $th.css({
                position: 'absolute',
            });
            $tr.css({
                position: 'absolute',
            });
            //$cloneTable.hide();
            //实际控制元素thFirst,th,tr第二列起
            //删除第二列起的td,头部第一行不需要删除
            $tr.each(function(i,v){
                $(v).find('td:gt(0)').remove();
            });
            /*
            * 交互元素分4种情况:tr第一行,tr第二行及以上,th第一列
            */
            let $trF = $tr.eq(0),
                $trS = $cloneTable.find('tr:gt(0)'),
                $thF = $th.eq(0);
            //
            if (type=='head') {
                $trS.remove()
                $parent.off().scroll(function(e){
                    let sTop = e.target.scrollTop,
                        sLeft = e.target.scrollLeft;
                    $trF.css({top: sTop});
                });
            } else {
                $parent.off().scroll(function(e){
                    let sTop = e.target.scrollTop,
                        sLeft = e.target.scrollLeft;
                    $trF.css({top: sTop});
                    $thF.css({left:sLeft});
                    $trS.css({left:sLeft});
                });
            }
        });
    };
    go();
    let timer = null,
        id = tableArr[0] || 'null';
    $(window).off('resize.'+id).on('resize.'+id,function(){
        clearTimeout(timer);
        console.log('resize');
        timer = setTimeout(() => {
            go();
        },300);
    });
},
//对table的tr,th,td处理,过程比上面的方法要复杂,会改变原table的一些样式,table上的事件可以继续调用
tableFixHead2({ tableArr = [], type = null }) {
    //默认是固定头部和第一列,可传参数type=head只固定头部
    let go = function () {
        tableArr.forEach((id) => {
            let $table = $(`#${id}`),
                $parent = $table.parent(),
                $tr = $table.find('tr'),
                $tr0 = $tr.eq(0),
                $th = $table.find('th'),
                $th0 = $th.eq(0),
                $td = $table.find('td'),
                col = $th.length,
                row = $tr.length;
            //在操作之前,要恢复table的默认状态
            $parent.scrollLeft(0);
            $parent.scrollTop(0);
            $tr.css({ 'position': 'static' });
            $th.css({ 'position': 'static' });
            $td.css({ 'position': 'static' });
            //设置th,需要重置宽度
            //return;
            $th.css({ 'width': 0 });
            $td.css({ 'width': 0 });
            let cache = {
                tr_height: [],
                tr_top: [],
                th_width: [],
                th_height: [],
                td_height: [],
                td_top: [], //td的定位只能相对table
            }
            let th0_width = $th.eq(0).outerWidth(),
                th0_height = $th.eq(0).outerHeight(),
                tr_width = $tr.eq(0).outerWidth();
            //收集
            $tr.each(function(i,v){
                cache['tr_height'].push( $(v).outerHeight() );
                cache['tr_top'].push( $(v).position().top );
            });
            $th.each(function (i,v) {
                cache['th_width'].push( $(v).outerWidth() );
                cache['th_height'].push( $(v).outerHeight() );
            });
            $td.each(function(i,v){
                cache['td_height'].push( $(v).outerHeight() );
                cache['td_top'].push( $(v).parent().position().top );
            });
            //设置th
            $th.each(function (i, v) {
                $(v).css({
                    width: cache['th_width'][i],
                });
            });
            //设置td
            $tr.each(function(i,v){
                $(v).find('td').each(function(i2,v2){
                    $(v2).css({
                        width: cache['th_width'][i2],
                        height: cache['tr_height'][i],
                        top: cache['tr_top'][i],
                    })
                });
            });
            //给第一列设置背景色
            $tr.each(function(i,v){
                $(v).children().eq(0).css({
                    'background-color': $(v).css('background-color'),
                })
            });
            //因为第一行tr绝对定位后,tr的宽度会变化,所以要补丁
            $table.css({width: tr_width});
            $tr0.css({
                left: 0,
                width: tr_width,
                'padding-left': th0_width,
            });
            //设置th0
            $th0.css({
                position: 'absolute',
                width: th0_width+1,
                left: 0,
                top: 0,
                'z-index': 2,
            });
            //设置第一列的td
            $tr.each(function(i,v){
                $(v).find('td').eq(0).css({
                    position: 'absolute',
                    left: 0,
                    width: th0_width+1,
                    height: cache['tr_height'][i]+1,
                });
            });
            //在head固定的时候,table会paddint-top,对于td而言,要补上这一差值
            function setTdPosition(left,top) {
                if (type=='head') {
                    $tr.each(function(i,v){
                        $(v).find('td').eq(0).css({
                            top: cache['tr_top'][i]+top,
                        })
                    });
                } else {
                    $tr.each(function(i,v){
                        $(v).find('td').eq(0).css({
                            left: left,
                            top: cache['tr_top'][i]+top,
                        })
                    });
                    $th0.css({
                        left: left,
                    })
                }
            };
            $parent.off().scroll(function (e) {
                let sTop = e.target.scrollTop,
                    sLeft = e.target.scrollLeft;
                if (sTop < th0_height) {
                    $tr0.css({ top: 0, position: 'static' });
                    $table.css({ 'padding-top': 0 });
                    setTdPosition(sLeft,0);
                } else {
                    $tr0.css({ top: sTop, position: 'absolute' });
                    $table.css({ 'padding-top': th0_height });
                    setTdPosition(sLeft,-th0_height+1);
                }
            });
        });
    };
    go();
    let timer = null,
        id = tableArr[0] || 'null';
    $(window).off('resize.' + id).on('resize.' + id, function () {
        clearTimeout(timer);
        console.log('resize');
        timer = setTimeout(() => {
            go();
        }, 300);
    });
},




  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值