JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题


Posted in Javascript onJune 30, 2017

正文

前言:一年前,博主分享过一篇关于bootstrapTable组件冻结列的解决方案  JS组件系列——Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案 ,通过该篇,确实可以实现bootstrapTable的冻结列效果,并且可以兼容ie浏览器。这一年的时间,不断有园友以及群里面的朋友问过我关于固定高度之后,冻结列页面效果不能对齐的问题,奈何博主太忙,一直没有抽空将这个问题优化。最近项目里面也不断有人提过这个bug,这下子不能再推了,必须要直面“惨淡的bug”,于是昨天利用一天的时间将原来的扩展做了一下修改,能够完美解决固定高度之后冻结列的问题,并且,博主还加了一些特性,比如右侧列的冻结、冻结列的选中等等,有需要的朋友可以捧个场。相信通过此篇,老板再也不用担心我的冻结列不能固定高度了~~

一、问题追踪

记得在之前的那篇里面介绍过,bootstrapTable组件自带的冻结列扩展,不能兼容ie浏览器,即使最新版本的ie也会无法使用,这是一般的系统不能忍受的,所以在那篇里面给出过解决方案,但并未分析ie浏览器不能兼容的原因,昨天博主花了点时间特意调试了下源码,原来在ie里面,使用jquery的clone()方法和谷歌等浏览器有所区别。为了展示这个区别,这里先抛个砖。比如有如下代码:

<table id="tbtest">
 <tr><td>aaa</td><td>bbb</td><td>ccc</td></tr>
 <tr><td>ddd</td><td>eee</td><td>fff</td></tr>
 <tr><td>ggg</td><td>hhh</td><td>iii</td></tr>
</table>
<script type="text/javascript">
 var $tr = $('#tbtest tr:eq(0)').clone();
 var $tds = $tr.find('td');
 $tr.html('');
 alert($tds.eq(0).html());
</script>

代码本身很简单,只是为了测试用。看到这里你可以试着猜一下alert的结果。

算了,不考大家了,直接贴出来吧,有图有真相!

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

相信不用我过多的解释哪个是ie,哪个是谷歌了吧。

两者的区别很明显,谷歌里面得到“aaa”,而ie里面得到空字符串。这是为什么呢?

其实如果你用值类型和引用类型的区别来解释这个差别你就不难理解了,在谷歌浏览器里面,$tr变量是一个引用类型,当你清空了它里面的内容,只是清除了$tr这个变量的“指针”,或者叫指向,$tds变量仍然指向了$tr的原始内容,所以调用$tds.eq(0).html()的时候仍然能得到结果aaa;同样的代码在ie浏览器里面,$tr变量就是一个值类型,你清空了它里面的内容之后,$tds的内容也被清空了。如果你有更好的解释,欢迎赐教哈。

之所以组件原生的js不能兼容ie浏览器,就是因为它使用了clone()这个方法,导致在不同的浏览器看到不同的结果。相信bootstrapTable组件的作者应该是知道这个区别的,只不过没有太在意这些,从作者做的很多功能的兼容性能够看出,他做的功能很多没有太多的考虑ie浏览器的效果。

二、效果预览

还是老规矩,说了这个多,没图怎么行,小二,上图!

没有固定高度的情况:单列冻结。

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

多列冻结。

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

 固定任意高度效果

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

ie浏览器也没有问题,这里就不再重复上图了。

三、源码解析

源码没啥说的,有兴趣可以自己看看,主要的原理还是重写bootstrapTable构造器的事件,来达到想要的效果。

(function ($) {
 'use strict';
 $.extend($.fn.bootstrapTable.defaults, {
  fixedColumns: false,
  fixedNumber: 1
 });
 var BootstrapTable = $.fn.bootstrapTable.Constructor,
  _initHeader = BootstrapTable.prototype.initHeader,
  _initBody = BootstrapTable.prototype.initBody,
  _resetView = BootstrapTable.prototype.resetView;
 BootstrapTable.prototype.initFixedColumns = function () {
  this.$fixedHeader = $([
   '<div class="fixed-table-header-columns">',
   '<table>',
   '<thead></thead>',
   '</table>',
   '</div>'].join(''));
  this.timeoutHeaderColumns_ = 0;
  this.$fixedHeader.find('table').attr('class', this.$el.attr('class'));
  this.$fixedHeaderColumns = this.$fixedHeader.find('thead');
  this.$tableHeader.before(this.$fixedHeader);
  this.$fixedBody = $([
   '<div class="fixed-table-body-columns">',
   '<table>',
   '<tbody></tbody>',
   '</table>',
   '</div>'].join(''));
  this.timeoutBodyColumns_ = 0;
  this.$fixedBody.find('table').attr('class', this.$el.attr('class'));
  this.$fixedBodyColumns = this.$fixedBody.find('tbody');
  this.$tableBody.before(this.$fixedBody);
 };
 BootstrapTable.prototype.initHeader = function () {
  _initHeader.apply(this, Array.prototype.slice.apply(arguments));
  if (!this.options.fixedColumns) {
   return;
  }
  this.initFixedColumns();
  var that = this, $trs = this.$header.find('tr').clone();
  $trs.each(function () {
   $(this).find('th:gt(' + (that.options.fixedNumber - 1) + ')').remove();
  });
  this.$fixedHeaderColumns.html('').append($trs);
 };
 BootstrapTable.prototype.initBody = function () {
  _initBody.apply(this, Array.prototype.slice.apply(arguments));
  if (!this.options.fixedColumns) {
   return;
  }
  var that = this,
   rowspan = 0;
  this.$fixedBodyColumns.html('');
  this.$body.find('> tr[data-index]').each(function () {
   var $tr = $(this).clone(),
    $tds = $tr.find('td');
   //$tr.html('');这样存在一个兼容性问题,在IE浏览器里面,清空tr,$tds的值也会被清空。
   //$tr.html('');
   var $newtr = $('<tr></tr>');
   $newtr.attr('data-index', $tr.attr('data-index'));
   $newtr.attr('data-uniqueid', $tr.attr('data-uniqueid'));
   var end = that.options.fixedNumber;
   if (rowspan > 0) {
    --end;
    --rowspan;
   }
   for (var i = 0; i < end; i++) {
    $newtr.append($tds.eq(i).clone());
   }
   that.$fixedBodyColumns.append($newtr);
   if ($tds.eq(0).attr('rowspan')) {
    rowspan = $tds.eq(0).attr('rowspan') - 1;
   }
  });
 };
 BootstrapTable.prototype.resetView = function () {
  _resetView.apply(this, Array.prototype.slice.apply(arguments));
  if (!this.options.fixedColumns) {
   return;
  }
  clearTimeout(this.timeoutHeaderColumns_);
  this.timeoutHeaderColumns_ = setTimeout($.proxy(this.fitHeaderColumns, this), this.$el.is(':hidden') ? 100 : 0);
  clearTimeout(this.timeoutBodyColumns_);
  this.timeoutBodyColumns_ = setTimeout($.proxy(this.fitBodyColumns, this), this.$el.is(':hidden') ? 100 : 0);
 };
 BootstrapTable.prototype.fitHeaderColumns = function () {
  var that = this,
   visibleFields = this.getVisibleFields(),
   headerWidth = 0;
  this.$body.find('tr:first-child:not(.no-records-found) > *').each(function (i) {
   var $this = $(this),
    index = i;
   if (i >= that.options.fixedNumber) {
    return false;
   }
   if (that.options.detailView && !that.options.cardView) {
    index = i - 1;
   }
   that.$fixedHeader.find('th[data-field="' + visibleFields[index] + '"]')
    .find('.fht-cell').width($this.innerWidth());
   headerWidth += $this.outerWidth();
  });
  this.$fixedHeader.width(headerWidth).show();
 };
 BootstrapTable.prototype.fitBodyColumns = function () {
  var that = this,
   top = -(parseInt(this.$el.css('margin-top'))),
   // the fixed height should reduce the scorll-x height
   height = this.$tableBody.height() - 18;
  debugger;
  if (!this.$body.find('> tr[data-index]').length) {
   this.$fixedBody.hide();
   return;
  }
  if (!this.options.height) {
   top = this.$fixedHeader.height()- 1;
   height = height - top;
  }
  this.$fixedBody.css({
   width: this.$fixedHeader.width(),
   height: height,
   top: top + 1
  }).show();
  this.$body.find('> tr').each(function (i) {
   that.$fixedBody.find('tr:eq(' + i + ')').height($(this).height() - 0.5);
   var thattds = this;
   debugger;
   that.$fixedBody.find('tr:eq(' + i + ')').find('td').each(function (j) {
    $(this).width($($(thattds).find('td')[j]).width() + 1);
   });
  });
  // events
  this.$tableBody.on('scroll', function () {
   that.$fixedBody.find('table').css('top', -$(this).scrollTop());
  });
  this.$body.find('> tr[data-index]').off('hover').hover(function () {
   var index = $(this).data('index');
   that.$fixedBody.find('tr[data-index="' + index + '"]').addClass('hover');
  }, function () {
   var index = $(this).data('index');
   that.$fixedBody.find('tr[data-index="' + index + '"]').removeClass('hover');
  });
  this.$fixedBody.find('tr[data-index]').off('hover').hover(function () {
   var index = $(this).data('index');
   that.$body.find('tr[data-index="' + index + '"]').addClass('hover');
  }, function () {
   var index = $(this).data('index');
   that.$body.find('> tr[data-index="' + index + '"]').removeClass('hover');
  });
 };
})(jQuery);
.fixed-table-header-columns,
.fixed-table-body-columns {
 position: absolute;
 background-color: #fff;
 display: none;
 box-sizing: border-box;
 overflow: hidden;
}
 .fixed-table-header-columns .table,
 .fixed-table-body-columns .table {
  border-right: 1px solid #ddd;
 }
  .fixed-table-header-columns .table.table-no-bordered,
  .fixed-table-body-columns .table.table-no-bordered {
   border-right: 1px solid transparent;
  }
 .fixed-table-body-columns table {
  position: absolute;
  animation: none;
 }
.bootstrap-table .table-hover > tbody > tr.hover > td {
 background-color: #f5f5f5;
}

如何使用呢?这里博主单独搞了一个静态的html测试页,还是贴出来供大家参考。

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
 <meta charset="utf-8" />
 <title></title>
 <!--必须的css引用-->
 <link href="Content/bootstrap/css/bootstrap.min.css" rel="stylesheet" />
 <link href="Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" />
<link href="Content/bootstrap-table/extensions/fixed-column/bootstrap-table-fixed-columns.css" rel="stylesheet" />
</head>
<body>
 <div class="panel-body" style="padding-bottom:0px;">
  <!--<div class="panel panel-default">
   <div class="panel-heading">查询条件</div>
   <div class="panel-body">
    <form id="formSearch" class="form-horizontal">
     <div class="form-group" style="margin-top:15px">
      <label class="control-label col-sm-1" for="name">员工姓名</label>
      <div class="col-sm-3">
       <input type="text" class="form-control" id="name">
      </div>
      <label class="control-label col-sm-1" for="address">家庭住址</label>
      <div class="col-sm-3">
       <input type="text" class="form-control" id="address">
      </div>
      <div class="col-sm-4" style="text-align:left;">
       <button type="button" style="margin-left:50px" id="btn_query" class="btn btn-primary">查询</button>
      </div>
     </div>
    </form>
   </div>
  </div>-->
  <div id="toolbar" class="btn-group">
   <button id="btn_add" type="button" class="btn btn-success">
    <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>新增
   </button>
  </div>
  <table id="tb_user"></table>
 </div>
 <!--新增或者编辑的弹出框-->
 <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
   <div class="modal-content">
    <div class="modal-header">
     <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
     <h4 class="modal-title" id="myModalLabel">操作</h4>
    </div>
    <div class="modal-body">
     <div class="row" style="padding:10px;">
      <label class="control-label col-xs-2">姓名</label>
      <div class="col-xs-10">
       <input type="text" name="Name" class="form-control" placeholder="姓名">
      </div>
     </div>
     <div class="row" style="padding:10px;">
      <label class="control-label col-xs-2">年龄</label>
      <div class="col-xs-10">
       <input type="text" name="Age" class="form-control" placeholder="年龄">
      </div>
     </div>
     <div class="row" style="padding:10px;">
      <label class="control-label col-xs-2">学校</label>
      <div class="col-xs-10">
       <input type="text" name="School" class="form-control" placeholder="学校">
      </div>
     </div>
     <div class="row" style="padding:10px;">
      <label class="control-label col-xs-2">家庭住址</label>
      <div class="col-xs-10">
       <input type="text" name="Address" class="form-control" placeholder="学校">
      </div>
     </div>
     <div class="row" style="padding:10px;">
      <label class="control-label col-xs-2">备注</label>
      <div class="col-xs-10">
       <textarea class="form-control" placeholder="备注" name="Remark"></textarea>
      </div>
     </div>
    </div>
    <div class="modal-footer">
     <button type="button" class="btn btn-default" data-dismiss="modal"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span>关闭</button>
     <button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk" aria-hidden="true"></span>保存</button>
    </div>
   </div>
  </div>
 </div>
  <!--必须的js文件-->
  <script src="Content/jquery-1.9.1.min.js"></script>
  <script src="Content/bootstrap/js/bootstrap.min.js"></script>
  <script src="Content/bootstrap-table/bootstrap-table.min.js"></script>
  <script src="Content/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
<script src="Content/bootstrap-table/extensions/fixed-column/bootstrap-table-fixed-columns.js"></script>
  <script type="text/javascript">
   //页面加载完成之后
   var data = [
    { Id: 1, Name: 'Jim', Age: 30, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 2, Name: 'Kate', Age: 30, School: '光明小学', Address: '深圳市', Remark: 'My Name is Jim Green' },
    { Id: 3, Name: 'Lucy', Age: 30, School: '光明小学', Address: '广州天河机场', Remark: 'My Name is Jim Green' },
    { Id: 4, Name: 'Lilei', Age: 30, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 5, Name: 'Lintao', Age: 30, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 6, Name: 'Lily', Age: 30, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 7, Name: 'Hanmeimei', Age: 30, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 8, Name: '张三', Age: 46, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 9, Name: '李四', Age: 23, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 10, Name: '王五', Age: 33, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 11, Name: '赵六', Age: 22, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 12, Name: 'Polly', Age: 300, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
    { Id: 13, Name: 'Uncle', Age: 50, School: '光明小学', Address: '北京市光明小学旁', Remark: 'My Name is Jim Green' },
   ];
   var childData = [
    { SourceField: 'A', BackField: 'BB' },
    { SourceField: 'CC', BackField: 'UU' },
    { SourceField: 'DD', BackField: 'J' },
   ];
   $(function () {
    //表格的初始化
    $('#tb_user').bootstrapTable({
     data: data,       //直接从本地数据初始化表格
     method: 'get',      //请求方式(*)
     toolbar: '#toolbar',    //工具按钮用哪个容器
     striped: true,      //是否显示行间隔色
     cache: false,      //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
     pagination: true,     //是否显示分页(*)
     sortable: false,      //是否启用排序
     sortOrder: "asc",     //排序方式
     queryParams: function (params) {
      return params;
     },         //传递参数(*)
     sidePagination: "client",   //分页方式:client客户端分页,server服务端分页(*)
     pageNumber: 1,      //初始化加载第一页,默认第一页
     pageSize: 5,      //每页的记录行数(*)
     pageList: [10, 25, 50, 100],  //可供选择的每页的行数(*)
     search: true,      //是否显示表格搜索,此搜索是客户端搜索,不会进服务端,所以,个人感觉意义不大
     strictSearch: true,
     showColumns: true,     //是否显示所有的列
     showRefresh: true,     //是否显示刷新按钮
     minimumCountColumns: 2,    //最少允许的列数
     height:400,
   selectItemName: 'parentItem',
     fixedColumns: true,
     fixedNumber: 6,
     //注册加载子表的事件。注意下这里的三个参数!
     onExpandRow: function (index, row, $detail) {
      InitSubTable(index, row, $detail);
     },
     columns: [{
      checkbox: true
     }, {
      field: 'Name',
      title: '姓名',
width:200
     }, {
      field: 'Age',
      title: '年龄',
width:200
     }, {
      field: 'School',
      title: '毕业院校',
width:200
     }, {
      field: 'Address',
      title: '家庭住址',
width:100
     }, {
      field: 'Remark',
      title: '备注',
width:100
     }, 
 {
      field: 'Remark',
      title: '备注',
width:100
     }, {
      field: 'Remark',
      title: '备注',
width:100
     }, {
      field: 'Remark',
      title: '备注',
width:100
     }, {
      field: 'Remark',
      title: '备注',
width:100
     }, {
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      field: 'Remark',
      title: '备注',
width:100
     },{
      title: '操作',
width:200,
      formatter: function (value, row, index) {//这里的三个参数:value表示当前行当前列的值;row表示当前行的数据;index表示当前行的索引(从0开始)。
       var html = '<button type="button" onclick="editModel('+row.Id+')" class="btn btn-primary"><span class="glyphicon glyphicon-pencil" aria- hidden="true" ></span >编辑</button >  ' +
          '<button type="button" onclick="deleteModel(' + row.Id + ')" class="btn btn-danger"><span class="glyphicon glyphicon-remove" aria- hidden="true" ></span >删除</button >';
       return html;
      }
     }],
     onEditableSave: function (field, row, oldValue, $el) {
      alert("更新保存事件,原始值为" + oldValue);
      //$.ajax({
      // type: "post",
      // url: "/Editable/Edit",
      // data: row,
      // dataType: 'JSON',
      // success: function (data, status) {
      //  if (status == "success") {
      //   alert('提交数据成功');
      //  }
      // },
      // error: function () {
      //  alert('编辑失败');
      // },
      // complete: function () {
      // }
      //});
     }
    });
    //新增事件
    $("#btn_add").on('click', function () {
$('#tb_user').bootstrapTable("resetView");
     //弹出模态框
     $("#myModal").modal();
     //给弹出框里面的各个文本框赋值
     $("#myModal input").val("");
     $("#myModal textarea").val("");
    });
   });
   //加载子表
   var InitSubTable = function (index, row, $detail) {
    var parentid = row.MENU_ID;
    var cur_table = $detail.html('<table></table>').find('table');
    //子表的初始化和父表完全相同
    $(cur_table).bootstrapTable({
     //url: '/api/MenuApi/GetChildrenMenu',
     data: childData,
     method: 'get',
     queryParams: { strParentID: parentid },
     ajaxOptions: { strParentID: parentid },
     clickToSelect: true,
     uniqueId: "MENU_ID",
     pageSize: 10,
     pageList: [10, 25],
   selectItemName: 'childItem'+index,
   checkboxHeader:false,
     columns: [{
      checkbox: true
     }, {
       field: 'SourceField',
      title: '源端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }, {
      field: 'BackField',
      title: '备端字段'
     }],
     //无线循环取子表,直到子表里面没有记录
     onExpandRow: function (index, row, $Subdetail) {
      //oInit.InitSubTable(index, row, $Subdetail);
     }
    });
   };
   //编辑事件
   var editModel = function (id) {
    //根据当前行的id获取当前的行数据
    var row = $("#tb_user").bootstrapTable('getRowByUniqueId', id);
    //弹出模态框
    $("#myModal").modal();
    //给弹出框里面的各个文本框赋值
    $("#myModal input[name='Name']").val(row.Name);
    $("#myModal input[name='Age']").val(row.Age);
    $("#myModal input[name='School']").val(row.School);
    $("#myModal input[name='Address']").val(row.Address);
    $("#myModal textarea[name='Remark']").val(row.Remark);
   }
   //删除事件
   var deleteModel = function (id) {
    alert("删除id为" + id + "的用户");
   }
  </script>
</body>
</html>
bootstrapTableFixColumns.html

代码释疑:

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

1、源码各个方法解释

  • BootstrapTable.prototype.initFixedColumns :当初始化的时候配置了fixedColumns: true时需要执行的冻结列的方法。
  • BootstrapTable.prototype.initHeader:重写组件的的初始化表头的方法,加入冻结的表头。
  • BootstrapTable.prototype.initBody:重写组件的初始化表内容的方法,加入冻结的表内容。 
  • BootstrapTable.prototype.resetView:重写“父类”的resetView方法,通过setTimeout去设置冻结的表头和表体的宽度和高度。
  • BootstrapTable.prototype.fitHeaderColumns:设置冻结列的表头的宽高。
  • BootstrapTable.prototype.fitBodyColumns :设置冻结列的表体的宽高,以及滚动条和主体表格的滚动条同步。

 2、对于上述抛出的ie和谷歌的兼容性问题的解析

查看BootstrapTable.prototype.initBody方法,你会发现里面写有部分注释。

this.$body.find('> tr[data-index]').each(function () {
  var $tr = $(this).clone(),
  $tds = $tr.find('td');
  //$tr.html('');这样存在一个兼容性问题,在IE浏览器里面,清空tr,$tds的值也会被清空。
  //$tr.html('');
  var $newtr = $('<tr></tr>');
  $newtr.attr('data-index', $tr.attr('data-index'));
  $newtr.attr('data-uniqueid', $tr.attr('data-uniqueid'));
  var end = that.options.fixedNumber;
  if (rowspan > 0) {
  --end;
  --rowspan;
  }
  for (var i = 0; i < end; i++) {
  $newtr.append($tds.eq(i).clone());
  }
  that.$fixedBodyColumns.append($newtr);
  if ($tds.eq(0).attr('rowspan')) {
  rowspan = $tds.eq(0).attr('rowspan') - 1;
  }
 });

这一段做了部分修改,有兴趣可以调适细看。

3、项目中的使用

 最近在研究学习abp的相关源码,将bootstrapTable融入abp里面去了,贴出表格冻结的一些效果图。

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

4、扩展

除此之外,还特意做了右边操作列的冻结。

JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题

和左边列的冻结一样,最右边列的冻结也是可以做的,最不同的地方莫过于右边列有一些操作按钮,如果在点击冻结列上面的按钮时触发实际表格的按钮事件是难点。如果有这个需求,可以看看。

bootstrap-table-fixed-columns.js
 bootstrap-table-fixed-columns.css

需要说明的是,由于时间问题,右侧固定列的代码和上述解决高度的代码并未合并,所以如果你既想要解决冻结列的高度,又想要右侧列的冻结,需要自己花点时间合并下代码。

以上所述是小编给大家介绍的JS 组件系列之Bootstrap Table的冻结列功能彻底解决高度问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
script标签属性type与language使用选择
Dec 02 Javascript
js点击更换背景颜色或图片的实例代码
Jun 25 Javascript
15款jQuery分布引导插件分享
Feb 04 Javascript
使用CoffeeScrip优美方式编写javascript代码
Oct 28 Javascript
javascript加减乘除的简单实例
Jul 12 Javascript
JavaScript动态绑定详解
Sep 14 Javascript
原生javascript实现文件异步上传的实例讲解
Oct 26 Javascript
JavaScript设计模式之装饰者模式定义与应用示例
Jul 25 Javascript
详解js获取video任意时间的画面截图
Apr 17 Javascript
微信小程序图片左右摆动效果详解
Jul 13 Javascript
浅析vue-router实现原理及两种模式
Feb 11 Javascript
jquery简易手风琴插件的封装
Oct 13 jQuery
MUI实现上拉加载和下拉刷新效果
Jun 30 #Javascript
js实现京东轮播图效果
Jun 30 #Javascript
jquery实现一个全局计时器(商城可用)
Jun 30 #jQuery
Vue和Bootstrap的整合思路详解
Jun 30 #Javascript
JavaScript原型继承_动力节点Java学院整理
Jun 30 #Javascript
JavaScript之排序函数_动力节点Java学院整理
Jun 30 #Javascript
JavaScript操作文件_动力节点Java学院整理
Jun 30 #Javascript
You might like
解析php类的注册与自动加载
2013/07/05 PHP
php使用memcoder将视频转成mp4格式的方法
2015/03/12 PHP
php替换字符串中间字符为省略号的方法
2015/05/04 PHP
php parse_str() 函数的定义和用法
2016/05/23 PHP
详解如何实现Laravel的服务容器的方法示例
2019/04/15 PHP
js中的escape及unescape函数的php实现代码
2007/09/04 Javascript
jquery属性过滤选择器使用示例
2013/06/18 Javascript
js使用for循环及if语句判断多个一样的name
2014/09/09 Javascript
jQuery实现悬浮在右上角的网页客服效果代码
2015/10/24 Javascript
jQuery使用serialize()表单序列化时出现中文乱码问题的解决办法
2016/07/27 Javascript
Vue.js每天必学之Class与样式绑定
2016/09/05 Javascript
常用的几个JQuery代码片段
2017/03/13 Javascript
angularjs实现分页和搜索功能
2018/01/03 Javascript
Vue.js 十五分钟入门图文教程
2018/09/12 Javascript
Vue多选列表组件深入详解
2021/03/02 Vue.js
[03:23:49]2016.12.17日完美“圣”典全回顾
2016/12/19 DOTA
python翻译软件实现代码(使用google api完成)
2013/11/26 Python
Python函数中的函数(闭包)用法实例
2016/03/15 Python
基于Python中numpy数组的合并实例讲解
2018/04/04 Python
Django项目中包含多个应用时对url的配置方法
2018/05/30 Python
10分钟教你用python动画演示深度优先算法搜寻逃出迷宫的路径
2019/08/12 Python
Python实现socket非阻塞通讯功能示例
2019/11/06 Python
python 串口读取+存储+输出处理实例
2019/12/26 Python
python实现xlwt xlrd 指定条件给excel行添加颜色
2020/07/14 Python
html+css实现自定义图片上传按钮功能
2019/09/04 HTML / CSS
荟萃全球保健品:维他购
2018/05/09 全球购物
PPP协议组成及简述协议协商的基本过程
2015/05/28 面试题
马云的职业生涯规划之路
2014/01/01 职场文书
大学生优秀自荐信范文
2014/02/25 职场文书
活动倡议书范文
2014/05/13 职场文书
建筑工地标语
2014/06/18 职场文书
党支部四风整改方案
2014/10/25 职场文书
教师远程研修感悟
2015/11/18 职场文书
小学毕业教师寄语
2019/06/21 职场文书
python字典的元素访问实例详解
2021/07/21 Python
python神经网络 使用Keras构建RNN训练
2022/05/04 Python