做后台列表时,因朋友推荐,尝试了一波DataTables,简单分享一下。
Datatables是一款jquery表格插件。它是一个高度灵活的工具,可以将任何HTML表格添加高级的交互功能。
1. 引入
Datatables基本功能只需要引入一个CSS和JS,可以从官网下载完整包或者直接使用官网提供的CDN。
另外如果需要使用按钮(比如用于实现扩展比如导出等功能时)、编辑器(给表格提供一个完整的编辑能力)等功能,还需要下载对应的插件。可以在这里找到 www.datatables.club/extensions/。
按钮插件这里还是比较推荐的,能够为常见的后台前端开发提供有效的支持。
当然,Datatables还提供Bootstrap样式,在官网下载包中有提供,可以自行引入。
2.使用
Datatables的使用推荐先耐心看官网文档(虽然文档有点拗,而且很多内容没有译文)。
——不想看文档的话,可以试试参考下面的简要使用方法。
a. HTML中简单添加table标签并标注id
如果不想在接下来的JS中配置表头,可以手动编辑页面中的thead标签及元素。
新手测试时可以先用table编写一个完整的table-thead-tbody结构对照。另外,table需要定义一个ID,DataTable将通过这个Id获得句柄进行操作。
b. 简单的Datatable启动器
例如我们的table id为example_table:
$('#example_table').DataTable( {} );
建议在所有内容加载后再执行本语句。
c. DataTable settings
由于表格中有很多配置项,我们可以将配置单独建立数组变量,方便修改和配置。这里我们命名为data_table_settings。里面的具体配置项比较简单,请自行翻译或参考文档。
以老九一个项目的setting配置举例:
var url="/index.php";
var columnDefs = [];
var data_table_settings = {
"ajax": {
type: "POST",
url: url,
},
"scrollX": true,
"columnDefs": columnDefs,
"bFilter": true,
'bDestroy': true,
"serverSide": true,
"searching": false,
// "lengthChange": false,
"fnServerParams": function (aoData) {
aoData._rand = Math.random();
},
// "fnDrawCallback": null,
"language": {
"sProcessing": "处理中...",
"sLengthMenu": "显示 _MENU_ 项结果",
"sZeroRecords": "没有匹配结果",
"sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
"sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
"sInfoFiltered": "(由 _MAX_ 项结果过滤)",
"sInfoPostFix": "",
"sSearch": "搜索:",
"sUrl": "",
"sEmptyTable": "表中数据为空",
"sLoadingRecords": "载入中...",
"sInfoThousands": ",",
"oPaginate": {
"sFirst": "首页",
"sPrevious": "上页",
"sNext": "下页",
"sLast": "末页"
},
"oAria": {
"sSortAscending": ": 以升序排列此列",
"sSortDescending": ": 以降序排列此列"
}
}
};
data_table = $('#data_table').dataTable(data_table_settings);
其实核心在上面,后面一大串的中文是语言包。最后记得使用定义好的配置对象初始化DataTable。
d. columnDefs
上例中我们可以看到我们定义了一个空数组columnDefs。columnDefs可以用来定义表头。例如我们可以这样操作:
columnDefs = [
{
"targets": 0,
"data": "avatar",
"title": "头像",
"orderable": false,
"className": "column-1",
"render": function (data) {
return url2tag(data);
}
},
{
"targets": 1,
"data": "name",
"title": "昵称",
"orderable": false,
"className ": "column-2",
}]
注:render可以对传入的data进行重组和处理,orderable表示是否参与排序。
通过columnDefs,我们可以将请求获得的Json数据分配给各个列。
e. ajax编写要求
DataTable ajax获取到的数据会自动解析为对象,不需要通过Json.parse。但是后端在响应请求时,我们需要接受指定的几个参数,并输出指定的参数以及封装好的Json格式数据。
e1. 获取信息:
//获取datatables信息
$length = intval($_REQUEST['length']);
$start = intval($_REQUEST['start'] / 10) + 1;
$draw = intval($_REQUEST['draw']);
$search = $_REQUEST['search'];
$order = $_REQUEST['order'][0]['column'] ? : 0;
$dir = $_REQUEST['order'][0]['dir'] ? : -1;
length:单页长度;
start: 传入的是从第“start”开始,这里为了方便ORM查询,我们将start转换为页码;
draw: DataTable用来匹配异步Ajax的标志;
search: 搜索词;
order和dir: 排序条件,以数组方式传入Boolean值。注意这里只有php能够直接解析post请求里的数组对象。
e2. 返回信息:
//最终组装
$rs['draw'] = $draw;
$rs['recordsTotal'] = $count;
$rs['recordsFiltered'] = $size;
$rs = json_encode($rs);
echo $rs;
draw: 与传入的draw标志对应即可;
recordsTotal: 总数;
recordsFiltered: 过滤后总数;
3. 其他运用
dataTable的功能还是比较强劲的,各种Api和插件虽然很方便,但是上手也比较麻烦。准备长期使用的朋友可以收藏本页面,需要寻找功能的时候去文档里查询即可。这里简单介绍几个老九使用的小技巧。
a. 注意dataTable()和DataTable()
两者都可以对表格执行渲染,但是又有些的不同。DataTable是老数据表构造,它返回一个jQuery对象。这个jQuery对象是丰富的的API方法,如fnfilter,fndeleterow等等。
总之如果你从网上找到各种各样的攻略,如果报错不妨注意一下这里。
官方文档的描述如下:
如果从DataTables 1.9或更早版本升级,您可能会注意到资本D用于初始化DataTable。$()。DataTable()返回DataTables API实例,而$()。dataTable()还将初始化DataTable,但返回一个jQuery对象。
官方论坛里的正解如下:
在初始化和您可以传递的选项方面,两者之间绝对没有区别。差异来自返回的对象。
使用$().dataTable()它返回一个jQuery对象,您可以将其用于jQuery样式链接(.eg addClass()和所有其他jQuery方法都可用)。这也是用于旧式1.9-API的选项,但如果您是DataTables的新手,我建议避免使用它。
使用$().DataTable()返回一个数据表API实例,而如果你想用工作,你会用数据表API。
b. fnServerParams
fnServerParams配置参数可以帮助我们往DataTable内的Ajax请求Post我们定制的信息。举例如下:
$("#action_zone").on('click', '#searchBtn', function () {
data_table_settings.fnServerParams = function (aoData) {
aoData._rand = Math.random();
aoData.daterange = $('#daterange').val();
aoData.type = $('#type').val();
aoData.query_type = $('#query_type').val();
aoData.search_word = $('#search_word').val();
}
data_table.fnDestroy(false);
data_table = $("#data_table").dataTable(data_table_settings);
//搜索后跳转到第一页
data_table.fnPageChange(0);
});
注意:这里我们使用的是jquery的$().on()语法,可以获得动态创建元素的行为。因为DataTable中我们很多控件都是动态创建的,而$().click()语法无法绑定,所以必须使用on语法。
注意2:这里我们启动DataTable时,需要使用dataTable();
c. 初始化和刷新
dataTable有很多种刷新的方法,我们可以使用Js刷新页面,也可以使用fnDestroy()销毁表格再重新创建(这种方法可以发送不同的配置和查询请求),也可以直接使用Draw()方法来重新绘制。
d. fnDrawCallback
很明显这是个回调。这里不是强调这个回调本身。而是介绍一种直接获取Ajax返回数据的方法。我们在使用DataTable时,数据都是直接传入表格单元的,有没有一种方法可以直接获取到返回的数据呢?如果需要单独再写一个Ajax,有感觉有些鸡肋。
解决方案如下:
data_table_settings.fnDrawCallback = function (oSettings) {
var json = jQuery.parseJSON(oSettings.jqXHR.responseText);
$("#sum").html(json.sum);
//console.log(json.sum);
//$("#pType").html("类型" + json.type.pType);
}
data_table = $('#data_table').dataTable(data_table_settings);
同样的,这里也需要使用dataTable();
e. column,row,cell
这些基本表格的要素使用就不一一介绍了,需要研究的可以慢慢看文档。需要对表格进行编辑和处理的话,还是蛮强大的,但是工程量也有些可观——前后端都得加班。
f. 推荐插件
由于表格查询通常用于后台等服务平台,一般我们还常用到DataRangePicker,SweetAlert等插件。
附上dataRangePicer的配置:
$('#daterange').daterangepicker(
{
autoUpdateInput: false,
applyClass: 'btn-sm btn-success',
cancelClass: 'btn-sm btn-default',
locale: {
applyLabel: '确认',
cancelLabel: '清空',
fromLabel: '起始时间',
toLabel: '结束时间',
customRangeLabel: '打开日历',
firstDay: 1
},
ranges: {
//'最近1小时': [moment().subtract('hours',1), moment()],
'今日': [moment().startOf('day'), moment()],
'昨日': [moment().subtract('days', 1).startOf('day'), moment().subtract('days', 1).endOf('day')],
'最近7日': [moment().subtract('days', 6), moment()],
'最近30日': [moment().subtract('days', 29), moment()]
},
opens: 'left', // 日期选择框的弹出位置
separator: ' 至 ',
showWeekNumbers: true, // 是否显示第几周
startDate: moment().startOf('day'),
format: 'YYYY/MM/DD',
timePicker: false,
showDropdowns: true
//timePicker: true,
//timePickerIncrement : 10, // 时间的增量,单位为分钟
//timePicker12Hour : false, // 是否使用12小时制来显示时间
//maxDate : moment(), // 最大时间
}, function (start, end, label) { // 格式化日期显示框
beginTimeStore = start;
endTimeStore = end;
console.log(this.startDate.format(this.locale.format));
this.element.val('');
console.log(this.endDate.format(this.locale.format));
if (!this.startDate) {
this.element.val('');
} else {
this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format));
}
});
$('#daterange').on('cancel.daterangepicker', function (ev, picker) {
//do something, like clearing an input
$('#daterange-btn').val('');
});