dataTables使用心得

因为公司的项目须要用到表格,因此我在网上找了许多的表格插件,对比之下,仍是以为dataTables这个插件比较好用。dataTables有不少的功能,具体能够查看官网 | 中文官网php

在这里我讲一下我在项目中使用到的功能。html

基础入门

dataTables 入门教程笔记node

1.常见的参数讲解

  • autoWidth - 自动计算列宽

这个值默认是true的,因此咱们不用去设置它web

  • serverSide - 开启服务器模式
  • ajax.data - 请求参数
  • ajax.dataSrc - 至关于jQuery的ajax的success
  • ajax - 请求url
  • data - 直接指定数据
  • destroy - 销毁表格对象
  • retrieve - 检索实例,检索当前存在的dt实例,继续使用它
  • columns.data - 指定数据源属性
  • columns.render - 渲染函数

data:当前数据, type:。。。, row:当前行,整行数据,可使用点语法来获取数据 metaajax

  • columns.visible - 设置列显示或隐藏
  • columnsDefs - 设置列的属性
  • dom - 表格定位

2.经常使用的回调方法和api

  • initComplete - 初始化完毕
  • footerCallback - tfoot回调函数
  • dt.ajax.reload() - 从新加载数据

dt指的是用datatables实例化后返回的对象,若是是用dataTables实例化,调用时应该带上api(),如table.api().ajax.reload(),若是是用DataTable实例化,则不用带上api(),如table.ajax.reload()json

  • dt.ajax.url().load() - 更换url并加载数据

url中能够带参数,即数据源连接
当url不带参数时,dt.ajax.url().load() == dt.ajax.reload()api

  • dt.ajax.url() - 更换url
  • dt.draw() - 重绘
  • $.fn.dataTable.util.throttle() - 减小方法执行次数,好比我在搜索的时候,我不想每次键入一个单词就搜索一次,我能够用这个函数来控制搜索延迟,能够是3s后搜索一次等

3.服务器模式

请求参数缓存

  • draw - 请求次数,即表示的是第几回请求
  • start - 起始位置,即分页起始位置
  • length - 长度,即分页长度
  • search[value] - 搜索框里的值
  • order[i][column] - 那一列排序
  • order[i][dir] - 排序方式
  • columns[i][data] - 列的属性名
  • columns[i][name] - 列的名字 须要配置 columns.name
  • columns[i][searchable] - 是否能被搜索
  • columns[i][orderable] - 是否排序
  • columns[i][search][value]

返回参数服务器

  • draw - 请求次数
  • recordsTotal - 总条数
  • recordsFiltered
  • data - 返回的数据
  • error

自定义dom

参考:DOM定位 基本初始化 示例 Datatables中文网 | option dom 自定义布局表格app

datatables默认会打开部分特性,好比搜索框,分页显示等等,或许你不喜欢datatables这样去布局,可能你想把分页按钮放在底部的中间,搜索框放在顶部的左上角,不用担忧datatables考虑到这个问题,使用dom选项就能够灵活配置各个特性的位置。

datatables定义了10个字符表示不一样的组件

  • l - Length changing 每页显示多少条数据选项
  • f - Filtering input 搜索框
  • t - The Table 表格
  • i - Information 表格信息
  • p - Pagination 分页按钮
  • r - pRocessing 加载等待显示信息
  • < and > - div elements 一个div元素
  • <”#id” and > - div with an id 指定id的div元素
  • <”class” and > - div with a class 指定样式名的div元素
  • <”#id.class” and > - div with an id and class 指定id和样式的div元素

我能够先放置一个占位的class,而后在表格实例化完成以后,再去动态添加元素,以此来实现高度可定制的dom。如:

dom: '<"dataTable-top table-toolBar"><"table-body"rt><"dataTable-bottom"lip><"clear">',

// 添加自定义dom
$('div.dataTable-top').html(searchBox + '<div class="clearfix">' + dataTableSearch + dataTableToolBar + '</div>');

服务器模式

参考:自行封装请求和返回数据的零耦合服务端分页 网友共享 示例 Datatables中文网

Datatables有许多方法来获取你的数据,若是你的数据量比较大,这个时候你须要使用服务器模式来处理你的数据。 在服务器模式下,全部的分页,搜索,排序等操做,Datatables都会交给服务器去处理。因此每次绘制Datatables, 都会请求一次服务器获取须要的数据。

经过配置serverSide这个属性来打开Datatables的服务器模式

serverSide: true,
processing: true, // 服务器加载数据等待提示

此时使用ajax来获取数据

"ajax": "../resources/server_processing_custom.php"

固然你也能够自定义ajax,好比个人项目中

ajax : function(data, callback, settings) {//ajax配置为function,手动调用异步查询
    console.log(data, callback, settings);
    //手动控制遮罩
    // $wrapper.spinModal();
    //封装请求参数
    var param = _this.getQueryCondition(data);
    $.ajax({
        type: "GET",
        url: "/api/employee",
        cache : false,  //禁用缓存
        data: param,    //传入已封装的参数
        dataType: "json",
        success: function(result) {
            //异常判断与处理
            if (result.errorCode) {
                // $.dialog.alert("查询失败。错误码:"+result.errorCode);
                return;
            }

            //封装返回数据,这里仅演示了修改属性名
            var returnData = {};
            returnData.draw = data.draw;//这里直接自行返回了draw计数器,应该由后台返回
            returnData.recordsTotal = result.total;
            returnData.recordsFiltered = result.total;//后台不实现过滤功能,每次查询均视做所有结果
            returnData.data = result.pageData;
            //关闭遮罩
            // $wrapper.spinModal(false);
            //调用DataTables提供的callback方法,表明数据已封装完成并传回DataTables进行渲染
            //此时的数据需确保正确无误,异常判断应在执行此回调前自行处理完毕
            console.log('success', returnData);
            callback(returnData);
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            $.dialog.alert("查询失败");
            $wrapper.spinModal(false);
        }
    });
},

添加序号和复选框

参考:给表格添加索引(Type selector-modifier 应用) | option columns.render 渲染列(1) 添加checkbox

首先必须定义好相关的列,添加复选框,使用render来渲染单元格dom元素

columns: [
    { //复选框单元格
        className: "td-checkbox",
        "searchable": false,
        "orderable": false,
        // width: "30px",
        data: null,
        render: function (data, type, row, meta) {
            return '<input type="checkbox" class="flat">';
        }
    },
    {
        data: null
    },
    {data: 'firstName'},
    {data: 'lastName'},
    {data: 'position'},
    {data: 'office'},
    {data: 'age'},
    {data: 'startDate'},
    {data: 'salary'},
    {data: 'extn'},
    {data: 'email'}
]

添加序号不能像复选框那样,而应该在表格生成完以后,再去渲染

'fnDrawCallback': function () {
    _this.table.column(1, {
        search: 'applied',
        order: 'applied'
    }).nodes().each(function(cell, i) {
        //i 从0开始,因此这里先加1
        i = i+1;
        //服务器模式下获取分页信息,使用 DT 提供的 API 直接获取分页信息
        var page = _this.table.page.info();
        //当前第几页,从0开始
        var pageno = page.page;
        //每页数据
        var length = page.length;
        //行号等于 页数*每页数据长度+行号
        var columnIndex = (i+pageno*length);
        cell.innerHTML = columnIndex;
    });
},

自定义搜索,服务器排序,分页

参考:自行封装请求和返回数据的零耦合服务端分页 网友共享 示例 Datatables中文网

在服务器模式下,经过改变传递到服务器的参数,来实现自定义搜索,排序和分页

getQueryCondition : function(data) {
    var param = {};
    //组装排序参数
    if (data.order&&data.order.length&&data.order[0]) {
        switch (data.order[0].column) {
            case 2:
                param.orderColumn = "firstName";
                break;
            case 3:
                param.orderColumn = "lastName";
                break;
            case 4:
                param.orderColumn = "position";
                break;
            case 5:
                param.orderColumn = "office";
                break;
            case 6:
                param.orderColumn = "age";
                break;
            case 7:
                param.orderColumn = "startDate";
                break;
            case 8:
                param.orderColumn = "salary";
                break;
            case 9:
                param.orderColumn = "extn";
                break;
            case 10:
                param.orderColumn = "email";
                break;
            default:
                param.orderColumn = "firstName";
                break;
        }
        param.orderDir = data.order[0].dir;
    }
    //组装查询参数
    param.fuzzySearch = this.fuzzySearch;
    if (param.fuzzySearch) {
        param.fuzzy = (!this.searching && this.localState !== null) ? this.localState.search.search : $("#tableSearch").val();
    }else{
        param.firstName = (!this.searching && this.localState !== null) ? this.localState.search.field.firstName : $("#firstName-search").val();
        param.lastName = (!this.searching && this.localState !== null) ? this.localState.search.field.lastName : $("#lastName-search").val();
        param.position = (!this.searching && this.localState !== null) ? this.localState.search.field.position : $("#position-search").val();
        param.office = (!this.searching && this.localState !== null) ? this.localState.search.field.office : $("#office-search").val();
        param.age = (!this.searching && this.localState !== null) ? this.localState.search.field.age : $("#age-search").val();
        param.startDate = (!this.searching && this.localState !== null) ? this.localState.search.field.startDate : $("#startDate-search").val();
        param.salary = (!this.searching && this.localState !== null) ? this.localState.search.field.salary : $("#salary-search").val();
        param.extn = (!this.searching && this.localState !== null) ? this.localState.search.field.extn : $("#extn-search").val();
        param.email = (!this.searching && this.localState !== null) ? this.localState.search.field.email : $("#email-search").val();
    }
    //组装分页参数
    param.startIndex = data.start;
    param.pageSize = data.length;
    param.draw = data.draw;

    console.log(param);

    return param;
}

记忆功能,保存状态

参考:关于 DataTables 本地储存那点事,又爱又恨 (stateSave参数应用)

//开启本地保存功能
stateSave: true,
    //保存状态操做
    "stateSaveParams": function (settings, data) {
    console.log("stateSaveParams", data, JSON.parse(localStorage.getItem('DataTables_' + settings.sInstance)));

    //这里能够操做保存的数据,写上本身特定的逻辑
    data.search.search = $("#tableSearch").val();
    data.search.fuzzySearch = _this.fuzzySearch;
    data.search.field = {
        firstName: $("#firstName-search").val(),
        lastName: $("#lastName-search").val(),
        position: $("#position-search").val(),
        office: $("#office-search").val(),
        age: $("#age-search").val(),
        startDate: $("#startDate-search").val(),
        salary: $("#salary-search").val(),
        extn: $("#extn-search").val(),
        email: $("#email-search").val()
    }
},
"stateSaveCallback": function (settings, data) {
    console.log("stateSaveCallback", data);

    //DT默认保存的key值为DataTables_+表格id+页面名称
    localStorage.setItem('DataTables_' + settings.sInstance, JSON.stringify(data));
},

//读取状态操做
"stateLoadParams": function (settings, data) {
    console.log("stateLoadParams", data);

    //在读取数据的时候能够改变数据,根据本身逻辑来处理
    //data.search.search = "";

    //或者你能够直接禁用从缓存里读取数据,只要直接返回false便可
    //return false;
},
"stateLoadCallback": function (settings) {
    console.log("stateLoadCallback", JSON.parse(localStorage.getItem('DataTables_' + settings.sInstance)));
    return JSON.parse(localStorage.getItem('DataTables_' + settings.sInstance));



},
//状态加载完后执行的回调函数
"stateLoaded": function (settings, data) {
    console.log("stateLoaded", data);

    //在这里你能够打印出保存的缓存数据
    //alert( 'Saved filter was: '+data.search.search );

},

其它功能

rowId: '_id', // 为每一行数据添加上id,此处的_id是从服务器获取的
// 多语言
language: {
    "lengthMenu": "每页 _MENU_ 条记录",
        "zeroRecords": "没有找到记录",
        "info": "第 _PAGE_ 页 ( 总共 _PAGES_ 页 )",
        "infoEmpty": "无记录",
        "infoFiltered": "(从 _MAX_ 条记录过滤)",
        "paginate": {
        "first": "<<",
            "previous": "<",
            "next": ">",
            "last": ">>"
    },
    "search": "模糊查询:"
},
paginationType: 'full_numbers', // 分页功能
"order": [[2, 'asc']], // 默认排序
initComplete: ... // 初始化完成
fnDrawCallback: ... // 渲染表格完成回调

我在项目中遇到的问题

参考:JQuery Datatable Ajax请求两次问题的解决

  1. 因为在服务器模式下,设置scrollX为true,顶部thead会有bug,因此不设置这个属性
  2. draw()方法会从新从服务器拉取数据,如下代码会致使ajax两次,因此我将添加行号放在了’fnDrawCallback’回调函数中
table = $('#aaa').DataTable({...});

// 初始化完成,添加行号
    table.on('order.dt search.dt',function() {
        table.column(1, {
            search: 'applied',
            order: 'applied'
        }).nodes().each(function(cell, i) {
            cell.innerHTML = i + 1;
        });
    }).draw();