基於JQuery可拖動列表格插件DataTables的踩坑記

前言html

最近項目中在使用可以拖動列調整列位置順序的表格插件---DataTables,這也是目前我找到的惟一一種存在有這種功能的插件。ajax

在查找使用方法的過程當中發現可用案例並很少,且大多言語不詳。本文將全面介紹此插件的使用過程。json

若是不是有拖動列調整列位置順序的需求,建議不要使用此插件,坑點較多。後面有時間我會寫一個名爲Bootstrap-table表格插件的使用方法,使用起來比這個插件強多了服務器

正文app

英文官網:https://datatables.net/框架

中文官網:http://www.datatables.club/ide

建議多多參考英文官網中reference(參考)https://datatables.net/reference/index和中文官網中的文檔http://www.datatables.club/reference函數

下載文件時儘可能不要在中文官網下載,由於下載不到須要的表格的其餘插件,英文官網下載地址:https://datatables.net/download/indexpost

下載方式就是選擇,Bootstrap,JQuery,DataTables,以及下面插件中ColReorder(此插件是拖動列所需的),在此只是提議,如何下載諸君自選this

服務器分頁方式

注意,本文只介紹服務器分頁方式,由於客戶端分頁方式很簡單,建立表格時寫上必要的參數,而後把數據傳入表格就完成了

DataTables是基於JQuery和Bootstrap的,因此在使用此插件前需引入這兩個庫(框架)所需的文件

引入在其餘地方下載後的JQuery和Bootstrap及在DataTables官網下載的文件

html代碼以下:

<table class="table table-striped display table-bordered" style="margin: 0;" cellspacing="0" width="100%" id="table"></table>

 

js代碼以下:

服務器配置代碼:

踩坑:特別注意,這裏的交互必須寫在表格的ajax配置項裏,若是寫在其餘地方傳入數據,則點第二頁後的頁數時顯示的頁數老是第二頁,且第一頁沒法點擊

複製代碼
let judgeTable = 0;
function table() {
  if(_this.judgeTable) {//這裏是爲了在初始化時表格不銷燬,不然會報錯
    $('#table').DataTable().destroy();//銷燬表格
  }
  _this.judgeTable = 1;
  $('#table').DataTable({
    colReorder: true,//啓動列拖動
    scrollX: true,//左右滾動條
    ordering: false,//排序
    searching: false,//參與搜索
    lengthMenu: [10, 25, 50, 100],//設置分頁大小選擇項目
    pageLength: _this.pageSize,//設置分頁大小
    displayStart: _this.pageNum - 1,//設置當前表格在第幾頁,從0開始
    serverSide: true,//是否開啓服務器分頁
    order: [[1, 'asc']],//asc按升序,desc按降序
    ajax: function (data, callback, settings) {
      //data參數中,data.length是單頁記錄條數;data.start是開始的記錄序號;(data.start / data.length)+1是當前頁碼
    $.ajax({
              url: _this.$ajaxConfig.url + "role/page?pageNum=" + _this.pageNum + "&pageSize=" + _this.pageSize,
              type: "GET",
              contentType: "application/json",
              cache: false,
              xhrFields: {
                withCredentials: true
              },
              success: function (result) {
                if(result.code == 0) {
                  let dataTable = [];
                  //修改行數據字段數據,以使表格識別,其中result是你要放到表格中的數據,若是你獲取到數據的字段和你在設置配置columns中的一致,則省略這個步驟
                  result.data.list.forEach(function (item,index) {
                    dataTable.push({
                      id: item.id,
                      name: item.name,
                      remark: item.remark,
                      enableEdit: item.enableEdit
                    })
                  })
                  //修改設置數據字段,以使表格識別
                  var returnData = {
                    recordsTotal: result.data.total,
                    recordsFiltered: result.data.total,
                    data: dataTable
                  };
                  callback(returnData);
                }
              },
              error: function (error) {
                console.log(error);
              }
            });
    },
    columns: [//列設置
      {
        data: null,
        checkboxes: {//這裏是複選框
          selectRow: true
        }
      },
      {
        title: "用戶名",
        data: "userName",
      },
      {
        title: "描述信息",
        data: "remark"
      },
      {
        title: "編輯用戶狀態",
        data: null,
        render: function (data, type, row, meta) {//render內設置此列單元格內容,我這裏是設置了按鈕
          //row是json對象行數據,放到元素中時需轉爲json字符串
          let rowData = JSON.stringify(row);
          let className = '';
          let elementText = '';
          if(row.flag) {
            className = 'csbtn-yes';
            elementText = '啓用';
          } else {
            className = 'csbtn-no';
            elementText = '禁用';
          }
        //這裏特別須要注意的是傳輸數據rowData不能使用雙引號包含,要麼使用單引號,要麼不使用引號
          return "<span class='csbtn " + className + "' data-table=" + rowData + " >" + elementText + "</span>";
        }
      }
    ],
    "language": {
      "lengthMenu": "每頁顯示 _MENU_ 條數據",
      "emptyTable": "暫無數據",
      "info": "顯示 _START_ 到 _END_ 共 _TOTAL_ 條",
      "infoEmpty": "顯示 0 到 0 共 0 條",
      "infoFiltered": "(從 _MAX_ 條中過濾)",
      "thousands": ",",
      "loadingRecords": "加載...",
      "processing": "加載中...",
      "search": "搜索:",
      "zeroRecords": "未找到相關數據",
      "select": {
        "rows" : ""
      },
      "paginate": {
        "first": "第一頁",
        "last": "最後一頁",
        "next": "下一頁",
        "previous": "上一頁"
      }
    },
  });
}
複製代碼

 

表格的相關事件:

踩坑:事件不要與建立表格代碼寫在一個函數內,不然單次觸發事件後觸發的次數會隨着點擊次數的增長,如:第一次觸發一次,第二次點擊後會自動觸發兩次

改變分頁大小事件:

$('#table').on('length.dt',function(e,settings,len) {
     pageSize = len;//改變存儲分頁大小的變量,len爲改變後的分頁大小
});

 

換頁事件:

$('#table').on( 'page.dt', function () {
       pageNum = $('#table').DataTable().page() + 1;//改變存儲當前頁數的變量,$('#table').DataTable().page()方法獲取到的是從0開始的當前頁數
 });

 

初始化事件:

$('#table').on('init.dt',function(e,settings,len) {
        console.log(e,settings,len)
});

 

選中行效果事件:

踩坑1:在添加點擊事件時,必須先使用off()移除事件,不然在不刷新頁面的前提下再次觸發表格從新渲染後會致使點擊一次後觸發屢次事件

踩坑2:這裏設置屬性checked時使用的是JQuery的prop方法,坑點是必須不能使用attr來設置屬性(使用後當點擊過複選框以後再設置此屬性則無效),由於JQuery在1.6版本後引入了一個prop這個方法,專門用來獲取表單屬性

複製代碼
$(document).off( 'click', '#role-table tbody tr');
$(document).on( 'click', '#role-table tbody tr', function () {
          //爲每行設置類名,而且操做複選框
          if($(this).hasClass('selected')) {
            $(this).removeClass('selected');
            $(this).find('td>input').prop("checked",false);
          } else {
            if(!$(this).hasClass('estimateRole')) {
              $(this).addClass('selected');
              $(this).find('td>input').first().prop("checked",true);
            }
          }
});
//點擊複選框是不會選中行的,因此還須要爲複選框設置事件
$(document).on( 'change', '#role-table tbody tr td input', function () {
          if($(this).parent().parent().hasClass('selected')) {
            $(this).parent().parent().removeClass('selected');
            $(this).parent().parent().find('td>input').prop("checked",false)
          } else {
            $(this).parent().parent().addClass('selected');
            $(this).parent().parent().find('td>input').first().prop("checked",true)
          }
});
$('#table').DataTable().rows('.selected').data();//獲取選中的行(帶有相應類名的行)
複製代碼

 

多層表頭:

使用多層表頭時,配置中的column須要換成columnFefs

複製代碼
columnDefs: [
            {
              "targets":[0],//第一列
              "orderable": false,
              "render": function (data, type, row, meta) {
                var text = "<input class='single-check-input'  type='checkbox'>";
                return text;
              }
            },
            {
              "targets":["json"],//最後一列
              "render": function (data, type, row, meta) {
                console.log(data)
                var text = "";
                text = "<a href=# onclick=showCollisonJsonData(this)>查看詳情</a>"
                return text;
              }
            },
]
複製代碼

 

配置表頭函數:

複製代碼
function configComplexHeader(headerInfo) {
        let _this = this;
        var theader = $('#detail-table-header');
        var headrFirstRow = $('<tr></tr>');
        var childHeaders = [];
        headerInfo.forEach(function (singleHeader) {
          var headerName = singleHeader.name;
          var colspanNum = singleHeader.childList.length;
          var thE = $('<th></th>',
            {
              colspan: colspanNum,
              text: headerName,
              style: "text-align:center"
            }
          );
          headrFirstRow.append(thE);
          (singleHeader.childList).forEach(function (childObj) {
            var childHeadTitle = childObj.name;
            if (childHeadTitle === "json_data") {
              childHeadTitle = "操做";
            }
            childHeaders.push(childHeadTitle);
          });
        });
        var tmpThE = $('<th/>',{
          colspan: 1,
        });
        headrFirstRow.prepend(tmpThE);

        var headerSecondRow = $('<tr></tr>');
        childHeaders.forEach(function (childHeader) {
          var className = "normal";
          if (childHeader === "操做") {
            className = "json";
          }
          headerSecondRow.append($('<th/>',{text:childHeader,class: className}));
        });

        var tmpSecThE = $('<th></th>',{
          class: "check-all-input-th",
          html: "<input type='checkbox' class='check-all-input'>"
        });
        headerSecondRow.prepend(tmpSecThE);
        theader.append(headrFirstRow);
        theader.append(headerSecondRow);
 }
//表頭數據
var headerInfo = [{"name":"碰撞字段","childList":[{"field":"col_c_cardno_3_0","name":"身份證號/身份證號"}]},
          {"name":"火車票數據","childList":[{"field":"c_mobile_1_0","name":"電話"},{"field":"c_email_2_0","name":"E-mail地址"},{"field":"a_name_1_0","name":"姓名"},{"field":"a_time_2_0","name":"訂票時間"},{"field":"a_time_3_0","name":"出發時間"},{"field":"json_data_0","name":"json_data"}]},
          {"name":"戶政人口","childList":[{"field":"a_name_1_1","name":"姓名"},{"field":"a_sex_2_1","name":"性別"},{"field":"a_address_3_1","name":"地址"},{"field":"a_marriage_4_1","name":"婚姻情況"},{"field":"a_edu_level_5_1","name":"文化程度"},{"field":"a_company_6_1","name":"單位"},{"field":"a_address_7_1","name":"籍貫"},{"field":"a_nation_8_1","name":"民族"},{"field":"json_data_1","name":"json_data"}]}]

configComplexHeader(headerInfo);
複製代碼

 

效果圖以下:

相關文章
相關標籤/搜索