zhangdongya

前言

上次写了一个可拖动列表的插件,但除了这个特点没什么优点了,接下写的是我们常用的Bootstrap-table表格插件

正文

官网:https://bootstrap-table.com/

有两个翻译API的网址:

https://blog.csdn.net/S_clifftop/article/details/77937356?locationNum=3&fps=1

https://blog.csdn.net/mrczr/article/details/64441265

在使用时需要引入如下几个文件:

bootstrap.min.css

bootstrap-table.css

jquery.js

bootstrap.js

bootstrap-table.js

bootstrap-table-zh-CN.js(中文插件)

客户端分页例如下:

// 首先销毁表格
$(\'#fwfx_tb\').bootstrapTable(\'destroy\');
// 初始化表格,动态从服务器加载数据
$(\'#fwfx_tb\').bootstrapTable({
  pagination: true,   //启动分页
  striped: true,    //设置为 true 会有隔行变色效果
  cache: false,                       //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
  pageSize: 20,//初始页记录数
  sortable: true,    //排序
  pageList: [10,20], //记录数可选列表
  smartDisplay: false,    //程序自动判断显示分页信息
  columns: [{
    title: \'序号\',
    align: \'center\',
    halign: \'center\',
    formatter: function (value, row, index) {
      return index + 1;
    }
  }, {
    field: \'name\',
    title: \'服务名\',
    align: \'center\',
    sortable:true    //排序
  }, {
    field: \'sum\',
    title: \'金额\',
    align: \'center\'
  }, {
    field: \'PV\',
    title: \'访问量\',
    align: \'center\'
  }
  data: tableData
});

 

服务器端分页例如下:

$(\'#user_content_tab\').bootstrapTable(\'destroy\');
        // 初始化表格,动态从服务器加载数据
        $(\'#user_content_tab\').bootstrapTable({
          url: "admin/query",
          method: \'post\',
          sidePagination: \'server\', //表示服务端请求
          queryParams:logUl,//请求服务器时所传的参数
          ajaxOptions:{   //提交ajax请求时的附加参数
            headers: {
              \'token\': \'94564375541867846\'//这里传的token是根据你的前后台交互情况
            }
          },
          toolbar : \'#toolbar\', // 工具按钮用哪个容器
          pagination: true, //默认为false,表格的底部工具栏不会显示分页条
          queryParamsType:\'\',//查询参数组织方式,必须设置为空,否则没有页码params.pageNumber
          striped: true,    //设置为 true 会有隔行变色效果
          pageSize: 20,    //每页显示行数
          pageList:[10,20,50],
          maintainSelected: true, //在点击分页按钮或搜索按钮时,将记住checkbox的选择项
          smartDisplay: false,    //程序自动判断显示分页信息
          clickToSelect: true,   //是否启用点击选中行
          toolbarAlign: \'right\',    //指定 toolbar 水平方向的位置
          uniqueId: \'userId\',    //为每一行指定唯一标识符
          idField: \'userId\',    //指定主键列
          paginationDetailHAlign:\'right\',//指定分页详细信息在水平方向的位置
          columns: [{
            title: \'序号\',
            align: \'center\',
            halign: \'center\',
            formatter: function (value, row, index) {
              var options = $table.bootstrapTable(\'getOptions\');
              return options.pageSize * (options.pageNumber - 1) + index + 1;
            }
          },{
            field: \'userId\',
            title: \'用户ID\',
            align: \'center\',
          },
            {
              field: \'username\',
              title: \'用户名称\',
              align: \'center\'
            },
            {
              field: \'roleName\',
              title: \'角色\',
              align: \'center\'
            },
            {
              field: \'createTime\',
              title: \'创建时间\',
              align: \'center\',
              formatter : function(value, row, index) {
                return fmtDate(value)
              }
            },
            {
              field: \'status\',
              title: \'账户状态\',
              align: \'center\'
            },
            {
              field: \'userId\',
              title: \'操作\',
              align: \'center\',
              width: 350,
              formatter: operateFormatter//在这里我的目的是添加按钮
            }],
          formatNoMatches: function(){
            return "没有相关的匹配结果";
          },
          formatLoadingMessage: function(){
            return "请稍等,正在加载中。。。";
          },
          responseHandler:function(res){  //加载服务器数据之前的处理程序,可以用来格式化数据,服务器返回的数据要在这里使用
            if(res.resCode == "403"){
              localStorage.clear();
              parent.location.href = location403;
            } else if(res.resStatus == 0) {
              for(var i = 0; i < res.resData.rows.length; i++) {
                if(res.resData.rows[i].status) {
                  res.resData.rows[i].status = \'启用\';
                } else {
                  res.resData.rows[i].status = \'禁用\';
                }
              }
              var cusData = {//这里的处理数据是根据你前后台交互的数据情况来的
                "rows": res.resData.rows,
                "total": res.resData.total
              }
              return cusData;
            } else {
              toastr.info(res.resMsg);
              return;
            }
          }
        });

        function logUl(params){
          pageNumbers = params.pageNumber;
          pageSizes = params.pageSize;
          return {
            "pageNo": params.pageNumber,
            "pageSize": params.pageSize,
            "username": queryVal
          }
        }

        function operateFormatter(value, row, index){  //添加按钮
          var rows = JSON.stringify(row);
          // 根据传过来的参数添加不同的class
          var classED = \'enabledE\';
          var classEDVal;
          if(row.status == \'启用\') {
            classED = \'enabledD\';
            classEDVal = \'禁用\';
          } else {
            classED = \'enabledE\';
            classEDVal = \'启用\';
          }
          // onclick=modif(\' + value + "," + rows + "," + index + \')
          return [
            \'<div class="modify operationBtn" title="重置密码" table-data=\' + rows + \'><i class="glyphicon glyphicon-pencil"></i>重置密码</div>\',
            \'<div class="enabled operationBtn \'+ classED + \'" title="禁用/启用" table-data=\' + rows + \'><i class="glyphicon glyphicon-user"></i>\' + classEDVal + \'</div>\',
            \'<div class="del operationBtn" title="删除" table-data=\' + rows + \'><i class="glyphicon glyphicon-trash"></i>删除</div>\'
          ].join("")
        }

 

拖动列来控制列宽的插件:

引入bootstrap-table-resizable.js和colResizable-1.6.min.js

$("#exampleTable").colResizable({
  liveDrag: true,//实时显示滑动位置
  gripInnerHtml: "<div class=\'grip\'></div>", 
  //draggingClass: "dragging",
  postbackSafe: true,//刷新后保留之前的拖拽宽度
  headerOnly:true,
  resizeMode:"overflow", 
  //onResize: onSampleResized
});

 

一些功能实现的样例:

1.选中

$(\'#generateClueObjectTable\').bootstrapTable(\'checkBy\', { field:"这里是选中行列字段", values:[这里选中行是列字段内的值,可多个]});

 

只可选中一行,使用check.bs.table事件(当用户选中一行时触发的事件)

$(\'#generateClueObjectTable\').on(\'check.bs.table\', function (row,element,input) {
  if (_this.addResearchReportTransObjectJudge) {
    let selections = $("#generateClueObjectTable").bootstrapTable(\'getSelections\');
    if (selections.length > 1) {
      $(\'#generateClueObjectTable\').bootstrapTable(\'uncheck\',input[0].dataset.index);
      _this.$message.error(\'只能选择一个对象\');
    }
  }
});

 

2.禁止全选操作,例:

check-all.bs.table 全选事件
$(\'#generateClueObjectTable\').on(\'check-all.bs.table\', function (row,element,input) {
  if(_this.addResearchReportTransObjectJudge) {
    $("#generateClueObjectTable").bootstrapTable(\'uncheckAll\');//阻止全选
  }
});

 

3.为复选框(checkbox)禁用或选中,例:

在复选框(checkbox)列中使用formatter

formatter: function (value, row, index) {
  return {
    disabled : true    //设置是否可用
    checked : true//设置选中
  }
}

 

4.在表格中嵌套表格,例:

columns:[{
  title: \'部门\',
  align: \'left\',
  sortable: false,
  formatter: function (value, row, index) {
    return row.deptName;
  }
},{
  field: \'\',
  title: "<table id=\"statisticTable\" class=\"tables\" style=\'border:1px solid             #bdd5dd;\'>" +
  "<thead><tr>" +
  "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">状态</th>" +
  "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">数量</th>" +
  "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">自主调研</th>" +
  "<th style=\"width:9%;padding-left: 10px;\" class=\"statisticTableTD\">上级交办</th>" +
  "</tr></thead>" +
  "</table>",
  align: \'left\',
  sortable: false,
  formatter: function (value, row, index) {
    var table = "<table class=\'table-keyValue\' style=\'border:1px solid             #d0e3e9;\'>";
    $.each(row.stats, function (i, item) {
      table += "<tr><td style=\"width:9%;\" class=\'statisticTableTD \'>" +             (item.statusCn == null ? 0 : item.statusCn) + "</td>"
        + "<td style=\"width:9%;\" class=\'statisticTableTD\'>" + (item.number == null             ? 0 : item.number) + "</td>"
        + "<td style=\"width:9%;\" class=\'statisticTableTD\'>" + (item.source1 == null ? 0 : item.source1) + "</td>"
        + "<td style=\"width:9%;\" class=\'statisticTableTD\'>" + (item.source0 == null ? 0 : item.source0) + "</td>" + "</tr>";
    });
    table += "</table>";
    return table;
  }
}]

 

5.实现多层表头

colspan 每格所占的列数
rowspan 每格所占的行数

columns: [
  [{
    title: \'这是标题\',
    field: \'\',
    align: \'center\',
    valign: \'middle\',
    colspan: 10
  }],
  [{
    title: \'这是标题1\',
    field: \'\',
    align: \'center\',
    valign: \'middle\',
    colspan: 1,
    rowspan: 2
  }, {
    title: \'这是标题2\',
    field: \'\',
    align: \'center\',
    valign: \'middle\',
    colspan: 4,
    rowsapn: 1
  }, {
    title: \'这是标题3\',
    field: \'\',
    align: \'center\',
    valign: \'middle\',
    colspan: 5,
    rowsapn: 1
  }],
  [{
    field: \'title1\', //列ID同时也是指定要显示的数据的ID
    title: \'标题\',
    width: 100,
    align: \'center\',
    valign: \'middle\',
    sortable: true
  },
    ......
 ]
]

 

下面是遇到的问题:

问题1.在设置为服务器端分页时,获取页码的params.pageNumber会返回undefined

这是因为queryParamsType的默认参数是limit,在官方说明中这样解释:

  "如果 queryParamsType = \'limit\' ,返回参数必须包含limit, offset, search, sort, order 否则, 需要包含: pageSize, pageNumber, searchText, sortName, sortOrder. 返回false将会终止请求"

有两种解决方法:

  1.为queryParamsType传空参数,即queryParamsType : "",这时没有params.limit,但可用params.pageSize来代替

  2.修改源码

  首先在bootstrap-table.min.js中搜索 "limit"===this.options.queryParamsType&& (完全复制过去搜索,当然因为版本的原因,一些版本代码细微处可能不太一样,但是肯定跟limit有关)找到下面的代码片段:

"limit"===this.options.queryParamsType&&(i={search:i.searchText,sort:i.sortName,order:i.sortOrder},this.options.pagination&&(i.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1),i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize))

可以看到在this.options.pagination&&后面的括号中有i.offset=...i.limit=...的代码,

i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize后面加上,i.pageNumber=this.options.pageNumber(记得一定要英文逗号分隔)

最终修改后结果如下:

"limit"===this.options.queryParamsType&&(i={search:i.searchText,sort:i.sortName,order:i.sortOrder},this.options.pagination&&(i.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1),i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize, i.pageNumber=this.options.pageNumber))

这样就可以通过params.pageNumber取到页码

 

问题2:在向表格内写入自定义元素时在列中使用formatter方法,但在元素中不可直接添加事件,否则无效,只可使用js获取元素后添加事件.

 

问题3:在向表格内写入自定义元素时在列中使用formatter方法,但在元素中添加行数据row时,必须先将json数据转为字符串才可使用,如:

var rows = JSON.stringify(row);

且在添加元素内时必须使用单引号(\'\')包含,如:

"<span class=\'classDataTable transRelateName\' table-data=\'" + JSON.stringify(row) + "\'>" + row.relateName + "</span>"

 

问题4:当表格中有点击事件的自定义元素时,换页会导致无法点击?
方法一(推荐,如果在vue等框架内要保证类名和事件函数内调用的函数是唯一的):在写点击事件时需要按如下方法书写:
$(document).on(\'click\', \'.researchName\', function () {}
方法二:把事件单独写一个函数,在表格中添加换页事件onPageChange,事件调用函数就行

 

问题5:设置列宽问题
  首先要给table加个下面的样式:
    table-layout: fixed;
  然后给列设置属性:
    width: 300

分类:

技术点:

相关文章: