当一个表格展示的数据相当多的时候,经常会用到固定列,固定行的事情
原理 是 两个或者多个表格组合行程 固定行或者固定列的情况 ,为了保障样式的统一性
当固定行的时候,要限定宽
当固定列的时候,要限定高
运用的插件 fixed-table.js 以及相关css
例子:
html部分:
//初始化FixedTable $(".fixed-table-box").fixedTable();
fixed-table.js
;(function (){ $.fn.extend({ fixedTable: function (){ var $this = this; return $this.each(function (index,item){ var $this = $(this); if(!$this.hasClass('fixed-table-box')){ return; } if($this.hasClass('head-fixed')){ return;} //计算表格的宽度 $.calFixedTableWidth(item); //计算固定列的高度 $.calFixedColHeight(item); //同步滚动 $.syncScroll(item); $this._setFixedIndex(); $this.rowHover(); }); }, getRow: function (row){ /*根据指定任意地方的行的索引、dom对象、jquery对象获取表格中表格主体、两侧固定列对应的行*/ var $this = this, rowDom = undefined, index = undefined, rows = []; if(typeof row != "number"){ rowDom = $(row); if(rowDom.length == 0){ return;} index = rowDom.index(); }else if(typeof row == "number"){ index = row; } if(index == undefined){ return this;} $this.each(function (index2, item){ var $item = $(item), row = { bodyRow: undefined, leftFixedRow: undefined, rightFixedRow: undefined }; if(!$item.hasClass('fixed-table-box')){ return;} var bodyRows = $item.children('.fixed-table_body-wraper').find("tr"), leftFixed = $item.children('.fixed-table_fixed-left'), rightFixed = $item.children('.fixed-table_fixed-right'); row.bodyRow = bodyRows.eq(index); if(leftFixed.length > 0){ row.leftFixedRow = leftFixed.children('.fixed-table_body-wraper').find("tr").eq(index); } if(rightFixed.length > 0){ row.rightFixedRow = rightFixed.children('.fixed-table_body-wraper').find("tr").eq(index); } rows.push(row); }); return rows; }, deleteRow: function (row, cb){ /*删除行,参数row可以是行的索引、dom对象、jquery对象*/ var $this = this; if(row == undefined){ return this;} return $this.each(function(index, item) { if(!$(item).hasClass('fixed-table-box')){ return;} var $item = $(item), rows = $item.getRow(row); if(!rows || rows.length == 0){ return;} $.each(rows, function (index, row){ if(row.bodyRow){ row.bodyRow.remove(); } if(row.leftFixedRow){ row.leftFixedRow.remove(); } if(row.rightFixedRow){ row.rightFixedRow.remove(); } $.calFixedColHeight(item); }); }); }, addRow: function (htmlDom, cb){ /*添加行,fn必须返回HTML字符串或jQuery对象*/ var $this = this, returnVal = undefined, rowDoms = undefined; if(!htmlDom){ return this;} if(({}).toString.call(htmlDom) == "[object Function]"){ returnVal = htmlDom(); }else{ returnVal = htmlDom; } if(!returnVal){ return this;} rowDoms = $(returnVal); if(rowDoms.length == 0){ return this;} return $this.each(function(index, item) { if(!$(item).hasClass('fixed-table-box')){ return;} var $item = $(item), $fixedTableBody = $item.children('.fixed-table_body-wraper').find("tbody"), $leftFixed = $item.children('.fixed-table_fixed-left'), $rightFixed = $item.children('.fixed-table_fixed-right'); $fixedTableBody.append(rowDoms); if(!item.fixedIndex){ return;} //给左侧固定栏添加数据 if(item.fixedIndex.left.length > 0 && $leftFixed.length > 0){ var cloneRows = rowDoms.clone(true), $leftFixedBody = $leftFixed.children('.fixed-table_body-wraper').find("tbody"), leftTrs = []; $.each(item.fixedIndex.left, function (index2, fixedIndex){ cloneRows.each(function(index3, cloneRow) { var leftTr = $(this).clone(true).html(""); $(cloneRow).find("td").each(function(index4, td) { if(index4 == fixedIndex.index){ leftTr.append(td); } }); leftTrs.push(leftTr); }); }); $leftFixedBody.append(leftTrs); } //给右侧固定栏添加数据 if(item.fixedIndex.right.length > 0 && $rightFixed.length > 0){ var cloneRows = rowDoms.clone(true), $rightFixedBody = $rightFixed.children('.fixed-table_body-wraper').find("tbody"), rightTrs = []; $.each(item.fixedIndex.right, function (index2, fixedIndex){ cloneRows.each(function(index3, cloneRow) { var rightTr = $(this).clone(true).html(""); $(cloneRow).find("td").each(function(index4, td) { if(index4 == fixedIndex.index){ rightTr.append(td); } }); rightTrs.push(rightTr); }); }); $rightFixedBody.append(rightTrs); } //添加数据后还需要设置两侧固定列的高度 $.calFixedColHeight(item); $(item).rowHover(); }); }, emptyTable: function (cb){ /*清空表格里的所有内容*/ var $this = this; return $this.each(function(index, item) { var $item = $(item); if(!$item.hasClass('fixed-table-box')){ return;} var bodyRows = $item.children('.fixed-table_body-wraper'), leftFixed = $item.children('.fixed-table_fixed-left'), rightFixed = $item.children('.fixed-table_fixed-right'); bodyRows.find("tbody").html(""); leftFixed.find(".fixed-table_body-wraper tbody").html(""); rightFixed.find(".fixed-table_body-wraper tbody").html(""); $.calFixedColHeight(item); }); }, rowHover: function (cb){ /*鼠标hover在每一行后所处理业务*/ var $this = this; return $this.each(function (index, item){ if(!$(item).hasClass('fixed-table-box')){ return;} var $item = $(item), hoverClass = $item.attr("data-hover") || "rowHover", $fixedTableBodyTrs = $item.children('.fixed-table_body-wraper').find("tr"), $leftFixed = $item.children('.fixed-table_fixed-left'), $rightFixed = $item.children('.fixed-table_fixed-right'); //为 避免多次绑定,在绑定事件前先将之前绑定的事件移除掉 $fixedTableBodyTrs.off("mouseenter.rowHover").off("mouseleave.rowHover"); $fixedTableBodyTrs.on("mouseenter.rowHover", _process).on("mouseleave.rowHover", _process); if($leftFixed.length > 0){ var $leftFixedTrs = $leftFixed.children('.fixed-table_body-wraper').find("tr"); $leftFixedTrs.off("mouseenter.rowHover").off("mouseleave.rowHover"); $leftFixedTrs.on("mouseenter.rowHover", _process).on("mouseleave.rowHover", _process); } if($rightFixed.length > 0){ var $rightFixedTrs = $rightFixed.children('.fixed-table_body-wraper').find("tr"); $rightFixedTrs.off("mouseenter.rowHover").off("mouseleave.rowHover"); $rightFixedTrs.on("mouseenter.rowHover", _process).on("mouseleave.rowHover", _process); } }); function _process(){ var $this = $(this), fixedTableBox = $this.parents(".fixed-table-box"), hoverClass = fixedTableBox.attr("data-hover") || "rowHover", rows = fixedTableBox.getRow($this.index()); if(!rows || rows.length == 0){ return;} $.each(rows, function(index, row) { row.bodyRow.toggleClass(hoverClass); if(row.leftFixedRow){ row.leftFixedRow.toggleClass(hoverClass); } if(row.rightFixedRow){ row.rightFixedRow.toggleClass(hoverClass); } }); } }, _setFixedIndex: function (){ /*存储固定列的下标*/ return this.each(function (){ var that = this, $this = $(this), $fixedTableHeaderTd = $this.children('.fixed-table_header-wraper').find('th'); if(this.fixedIndex){ return;} /*固定列的下标,数组的内容必须是一个对象,且对象格式为 { index: 0,//下标 direction: "left"//固定列方向 } */ this.fixedIndex = {}; $fixedTableHeaderTd.each(function(index, th) { if(th.hasAttribute("data-fixed")){ var direction = ($(th).attr("data-direction") || "left").toLowerCase(); if(!that.fixedIndex.left){ that.fixedIndex.left = []; } if(!that.fixedIndex.right){ that.fixedIndex.right = []; } that.fixedIndex[direction].push({ index: index, direction: direction }); } }); }); } }); $.extend({ calFixedColHeight: function (fixedTableBox){ /*计算两侧固定列的高度,及右侧固定列的位置*/ if(!$(fixedTableBox).hasClass('fixed-table-box')){ return this;} var $fixedTableBox = $(fixedTableBox), $fixedTableHeader = $fixedTableBox.children('.fixed-table_header-wraper'), $fixedTableBody = $fixedTableBox.children(".fixed-table_body-wraper"), fixedTableBody = $fixedTableBody[0], $fixedTableLeft = $(".fixed-table_fixed-left"), $fixedTableRight = $(".fixed-table_fixed-right"), hasCrosswiseScroll = true,//用于判断固定列的高度是否要减去滚动条的宽度,这样才不会遮住水平滚动条 hasVerticalScroll = false,//用于判断右侧的固定列的right值是否需要加上滚动条的宽度,这样才能显示出垂直滚动条 scrollWidth = 0, scrollWidth2 = 0, maxHeight = 0, isIE = $.isIE(); if(isIE){ //IE浏览器 /*在IE浏览器中$fixedTableBox.height()、$fixedTableBox[0].offsetHeight获取的高度 都为0,不知道为什么,但$fixedTableBox[0].clientHeight和$fixedTableBox[0].scrollHeight都有值, 为了保证两边的固定列能出来,所以就使用了这种解决方案*/ maxHeight = $fixedTableBox.height() || $fixedTableBox[0].clientHeight || $fixedTableBox[0].scrollHeight; }else{ maxHeight = $fixedTableBox.height(); } if(fixedTableBody.scrollWidth > fixedTableBody.clientWidth || fixedTableBody.offsetWidth > fixedTableBody.clientWidth){ hasCrosswiseScroll = true; }else{ hasCrosswiseScroll = false; } /*如果有水平滚动条fixedTableBody.offsetHeight会把水平滚动条的高度也计算进去,因此这里需要减去水平滚动条的高度*/ if(fixedTableBody.scrollHeight > fixedTableBody.clientHeight || (fixedTableBody.offsetHeight - $.getScrollWidth()) > fixedTableBody.clientHeight){ hasVerticalScroll = true; }else{ hasVerticalScroll = false; } if(hasCrosswiseScroll){ scrollWidth = $.getScrollWidth(); } if(hasVerticalScroll){ scrollWidth2 = $.getScrollWidth(); if($fixedTableBox.find(".fixed-table-box_fixed-right-patch").length == 0){ var rightPatch = $(' '), height = $fixedTableHeader.height(); rightPatch.css({ width: scrollWidth2, height: height-2 }); $fixedTableBox.append(rightPatch); } }else{ if($fixedTableBox.find(".fixed-table-box_fixed-right-patch").length == 0){ $fixedTableBox.find(".fixed-table-box_fixed-right-patch").remove(); } } var height = maxHeight - scrollWidth, fixedTable = $fixedTableBox.find(".fixed-table_fixed"); if(fixedTable.height() != Math.abs(maxHeight - scrollWidth)){ var height = maxHeight - scrollWidth; fixedTable.height(maxHeight - scrollWidth); } $fixedTableBox.find(".fixed-table_fixed.fixed-table_fixed-right").css("right", (scrollWidth2-1) < 0 ? 1 : (scrollWidth2 - 1)); return $fixedTableBox; }, calFixedTableWidth: function (fixedTableBox){ /*计算表格的宽度*/ if(!$(fixedTableBox).hasClass('fixed-table-box')){ return this;} var $this = $(fixedTableBox), $body = $("body"), $fixedTableHeader = $this.children().children(".fixed-table_header"), $fixedTableBody = $this.children().children(".fixed-table_body"), $cloneNode = $fixedTableHeader.clone(true), width = 0; $cloneNode.css({ position: "fixed", top: "-1000px" }); $body.append($cloneNode); width = $cloneNode.width(); $fixedTableHeader.width(width); $fixedTableBody.width(width); $cloneNode.remove(); return this; }, syncScroll: function (fixedTableBox){ /*同步滚动*/ if(!$(fixedTableBox).hasClass('fixed-table-box')){ return this;} var $fixedTableBox = $(fixedTableBox), fixedTableHeader = $fixedTableBox.children(".fixed-table_header-wraper"), $fixedTableBody = $fixedTableBox.children('.fixed-table_body-wraper'), $fixedCols = $fixedTableBox.children('.fixed-table_fixed').children('.fixed-table_body-wraper'); $fixedTableBody.on("scroll", function (){ var $this = $(this); fixedTableHeader.scrollLeft($this.scrollLeft()); $fixedCols.scrollTop($this.scrollTop()); }); return this; }, getScrollWidth: function (){ /*获取元素或浏览器滚动条的宽度*/ var div = document.createElement("div"), w1 = 0, w2 = 0; document.body.appendChild(div); div.style.position = "fixed"; div.style.left = "-2000px"; div.style.width = "200px"; div.style.height = "200px"; w1 = div.clientWidth; div.style.overflow = "scroll"; w2 = div.clientWidth; document.body.removeChild(div); return w1-w2; }, isIE: function (){ /*判断浏览器是否为IE浏览器*/ var ua = navigator.userAgent.toLowerCase(); if(/msie \d/g.test(ua) || ((/trident\/\d/g.test(ua)) && /like gecko/g.test(ua))){ return true; }else{ return false; } } });})();
fixed-table.css
@charset "utf-8";body{ margin: 0; padding: 0;}.fixed-table-box table { border-spacing: 0; border-collapse: collapse; box-sizing: border-box;}.fixed-table-box tr,.fixed-table-box td,.fixed-table-box th { box-sizing: border-box;}.fixed-table-box{ position: relative; font-size: 14px; line-height: 1.42858; border: 1px solid #dfe6ec; border-bottom: 0; border-right: 0; overflow: hidden;}.fixed-table-box:before{ display: block; position: absolute; bottom: 0; left: 0; content: " "; width: 100%; height: 1px; background-color: #dfe6ec;}.fixed-table-box:after{ display: block; position: absolute; top: 0; right: 0; content: " "; width: 1px; height: 100%; background-color: #dfe6ec;}.fixed-table-box .fixed-table_header,.fixed-table-box .fixed-table_body{ width: auto;}.fixed-table-box table{ background-color: #fff; border: 0;}.fixed-table-box th,.fixed-table-box td{ position: relative; text-align: left; padding: 5px 0; border: 1px solid #dfe6ec;}.fixed-table-box .table-cell{ display: block; height: 30px; line-height: 30px; word-break: break-all; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding-left: 15px;}/* 表头 start */.fixed-table-box>.fixed-table_header-wraper{ overflow: hidden;}.fixed-table-box .fixed-table_header.fixed-header{ position: absolute; top: 0; left: 0; width: 100%;}.fixed-table-box .fixed-table_header tr{ background-color: #eef1f6;}.fixed-table-box .fixed-table_header th{ color: #1f2d3d; border-top: 0; border-left: 0;}/* 表头 end *//*表格内容 start*/.fixed-table-box .fixed-table_body td{ border-top: 0; border-left: 0;}.fixed-table-box .fixed-table_body tr.rowHover{ background-color: #eef1f6;}/*表格内容 end*//* 行固定表格 start*/.fixed-table-box.head-fixed .fixed-table_body-wraper{ overflow-y: auto;}.fixed-table-box.head-fixed .fixed-table_header,.fixed-table-box.head-fixed .fixed-table_body{ width: 100%;}/* 行固定表格 end*//* 列固定表格 start */.fixed-table-box.col-fixed{ /* overflow-x: auto; */ border-right: 1px solid #eef1f6;}.fixed-table-box.col-fixed:after{ display: none;}.fixed-table-box.col-fixed .fixed-table_header-wraper{ /*设置它为overflow: hidden的目的是为了在拖动.fixed-table-box.col-fixed .fixed-table_body-wraper 的时候可以同步的拖动.fixed-table-box.col-fixed .fixed-table_header-wraper*/ overflow: hidden;}.fixed-table-box.col-fixed .fixed-table_body-wraper{ overflow-x: auto;}/* 列固定表格 end *//* 固定列 start */.fixed-table_fixed{ position: absolute; top: 0; z-index: 5; background-color: #fff; overflow: hidden;}.fixed-table_fixed-left{ left: 0; box-shadow: 1px -1px 8px 1px #d3d4d6;}.fixed-table_fixed-right{ right: 0; /* border-left: 1px solid #dfe6ec\0; */ box-shadow: -2px -1px 8px 1px #d3d4d6;}.fixed-table_fixed .fixed-table_header-wraper,.fixed-table_fixed .fixed-table_body-wraper{ overflow-y: hidden;}.fixed-table_fixed.fixed-table_fixed-right td{ border-right: none; border-left: 1px solid #dfe6ec;}/* 固定列 end *//* 固定列和固定表头 start */.fixed-table-box.row-col-fixed>.fixed-table_body-wraper{ overflow: auto;}.fixed-table-box_fixed-right-patch{ /*右上角的遮罩,如果少了这块在右边有固定列并且表格内容右侧有滚动条时会出现镂空的效果*/ background-color: #eef1f6; position: absolute; top: 0; right: 0;}/* 固定列和固定表头 end */
页面内样式:
/*固定列*/ .fixed-table-box{ max-width: 1200px; min-width: 1010px; /*margin: 50px auto;*/ } .fixed-table-box>.fixed-table_body-wraper{ /*内容了表格主体内容有纵向滚动条*/ max-height: 260px; /*margin-right: -12px;*/ } .fixed-table_fixed>.fixed-table_body-wraper{ /*为了让两侧固定列能够同步表格主体内容滚动*/ max-height: 240px; } .fixed-table-box td{ height: 37px!important; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .w-150{ width: 150px; } .w-120{ width: 120px; } .w-300{ width: 300px; } .w-100{ width: 100px; } .w-110{ width: 110px; } .w-80{ width: 80px; } .btns{ text-align: center; } .btns button{ padding: 10px 20px; } .fixed-table_body-wraper::-webkit-scrollbar { /*滚动条整体样式*/ width: 12px; /*高宽分别对应横竖滚动条的尺寸*/ height: 12px; } .fixed-table_body-wraper::-webkit-scrollbar-thumb { /*滚动条里面小方块*/ border-radius: 5px; -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); background: rgba(0,0,0,0.2); } .fixed-table_body-wraper::-webkit-scrollbar-track { /*滚动条里面轨道*/ -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2); border-radius: 0; background: rgba(0,0,0,0.1); }
这里有一个样式注意点
有的浏览器 td 不会按照规定的宽度展示,可以在里面的table-cell 加上宽度类名 防止 样式跑版
table-cell的话 一定要box-sizing:border-box;word-break: break-all;white-space:nowarp;overflow:hidden;text-overflow:ellipsis;
邀请单位