今天真的被这破插件气疯了,于是有了下面的截图。此文不定期更新,要是有新坑欢迎来填。
jQuery DataTables 的几个坑,监听、重载等等
看看截图娱乐娱乐
好了,正事儿要紧,先来说说这玩意儿的加载过程
首先必不可少的
jQuery
、DataTables.js
、DataTables.css
的引入略过我们先手写好一张
table
表格,大概就像下面这样<!-- 我就写简单点,去掉了所有 class,根据样式自己添加 --> <table id="user-list"> <thead> <tr> <th>ID</th> <th>账号</th> <th>用户组</th> <th>账号状态</th> <th>添加时间</th> <th>操作</th> </tr> </thead> <!-- tbody 这儿留空,依靠 Ajax 返回的数据填充 --> <tbody></tbody> </table>
来吧,先大概写个 JS
说一下,下方的一些参数,大家在网上可能经常看到
a
、b
开头的写法,那是旧式写法,当然是不影响使用的,推荐用新驼峰写法。对应表:Datatables | 升级 | 1.10.x与1.9.x参数名对照表// 根据上面的 HTML 代码操作,上方已定义 table 的 id 为 user-list var table = $('#user-list'); table.dataTable({ /** * 分页的几个显示方式,大致翻译一下 * `numbers` - 仅含页码按钮 * `simple` - 仅含“上一页”和“下一页” * 'simple_numbers` - “上一页”和“下一页”,加上页码 * `full` - “首页”,“上一页”,“下一页”,“尾页”按钮 * `full_numbers` - “首页”,“上一页”,“下一页”,“尾页”按钮以及页码 * `first_last_numbers` - “首页”和“尾页”按钮,加上页码 */ pagingType: 'full_numbers', // 所以这儿我用了 full_numbers lengthMenu: [10, 15, 20], // 可选每页显示数量 serverSide: true, // 服务端分页 searching: true, // 过滤功能 ordering: true, // 排序功能 columnDefs: [{ orderable: false, targets: [1, 2, 5] // 指定不排序列,下标 0(比如 ID,从 0 开始数,此处帐号、用户组和操作不能排序) }], language: { url: '/assets/js/plugins/datatables/Chinese.json' // 语言文件,下方会贴出来 }, ajax: { url: '', // 异步请求地址,没啥好说的 type: 'get', // 请求方式,因为是取数据,所以我选择了 get data: '' // 额外请求参数,一般是不需要的 }, // 暂时先写这部分,下部分再慢慢道来 });
官方对于服务器端的说明在这儿:服务器处理(server-side) 手册 Datatables 中文网
当然了,
爱看不看…从“服务器需要返回的数据(Returned data)”这一段(上方链接带上了锚点,访问即可到达),我们可以看到服务端需要返回什么数据:名称 类型 简述 draw integer|JS
DataTables 每次发送请求会带上这个参数,接收到以后转成 int
类型返回去就行。PHP 直接intval($draw)
非常方便recordsTotal integer|JS
总记录数(未过滤) recordsFiltered integer|JS
记录数(已过滤/检索) data array|Type
重点数据,靠这玩意儿完成数据填充 error string|JS
可选:这个参数用于异常时返回一个提示 - - 下方是额外参数,爱看不看 too。下方参数要放进 data 里数组的每一个元素内(不明白?没事…后面有示例) DT_RowId string|JS
表格每行数据,也就是 <tr>
上加一个 IDDT_RowClass string|JS
同上 <tr>
加一个class
样式DT_RowData object|JS
扔一点数据到 columns.render
的row
参数里DT_RowAttr object|JS
为 <tr>
添加一个属性,例如<tr data-val="what">
- - 这部分额外参数通过服务端传入,并自动绑定。无需额外操作 通过上方表格的简述,我们知道了
DataTables
需要从服务端返回什么数据,下面就是一个简单的数据格式返回,代码为“拍黄片”PHP
// 假设我们已经从数据库拿到用户列表并存入了变量 $userList // 在这儿先对数据进行一次处理,便于前端显示 foreach ($userList as $key => $val) { $userList[$key]['DT_RowClass'] = "text-center"; // 可忽略这个 $userList[$key]['add_time'] = date('Y-m-d H:i', $val['add_time']); // 格式化时间 $userList[$key]['operate'] = [ // 解释一下这个,因为我们 HTML 中最后一列是操作,含有编辑和删除功能,数据库肯定是没有这个相关数据的,我们模拟一个 `operate` 列出来。放入 ID 是因为我们编辑和删除需要这货啊! 'id' => $val['id'] ]; } $data = [ // 前面说了这个按照接收数据来返回,为了防止 XSS 攻击 // 我这儿就没详写,因为我用 Laravel 框架这儿直接 $request->draw 'draw' => 1, // 用户数据存入 data 'data' => $userList, // 总记录数(不过滤) 'recordsTotal' => $count, // 实际有多少就是多少 // 记录数(已过滤) 'recordsFiltered' => $filteredCount // 经过检索/过滤后的 ]; if (!$userList) { $data['error'] = '这儿什么也没有'; } // 实际上...在 Laravel 框架中直接 return $data 会自动变成 Json,嘿...嘿嘿嘿 return json_encode($data);
这儿再说一下排序,我是这么做的。还是爱看不看…
// 依旧是 Laravel 框架,$request->order 这个可以看成 _GET['order'] // 接收请求拿到 DataTables 传过来的 order $order = $request->order; // 将排序字段名和值组合成新数组 $order = [ $request->columns[$order[0]['column']]['data'] => $order[0]['dir']]; // 此时的 $order 是一个数组,形式为 id => desc。原谅没有加引号,不然这段代码颜色会错 // 在写取数据方法的时候建议给 $order 一个默认值
现在数据拿到了,再来处理处理第
3
步未完成的 JS// 其实也就是再加一个 columns。注意下方代码和第 3 步是衔接的 columns: [ // 这里 data 后的值如果 SQL 语句正常默认就是字段名 {data: 'id'}, {data: 'username'}, { // 这里也是一段重要的说明,如下代码,我数据库内 status 状态存的数字 // 在这儿总不能显示 0 和 1 吧?我们需要通过 render 方法来执行一些数据处理 // 当然也可以加一些样式在这个地方,文章末尾会有截图可供参考 data: 'status', render: function (data) { var content; switch (data) { case 0: content = '已禁用'; break; case 1: content = '正常'; break; case -1: content = '已删除'; break; } return content; } }, {data: 'add_time'}, { // 对了,前文的额外参数 DT_RowData,在下行 function 括号内的第三个参数可以获取。 // 当然我前面并没有传入这个数据,所以下行的 type 和 row 并未使用,可删除 data: 'operate', render: function (data, type, row) { // TODO: return(string); /* 这里的代码我就不写上来了,关于操作前面说了就是两个按钮,一个编辑一个删除 每个人的样式不一样,而我前面的 PHP 代码里给 data 传了一个 ID 此处可以通过 data.id 得到其值 类似这样:return '<button data-id="' + data.id + '"></button>'; 至此,数据已经可以拿到并成功显示啦! */ } } ]
低调上图:(文中精简了不少东西嘛,使用 BootStrap 样式更佳哦~)
Emmm…一不小心就把这货写清楚了
这儿说说我遇到的几个坑:
首先第一个!不要去重复
table.dataTable({});
。不然就是一个弹框提示你无法重新初始化,顶部图1的由来。前文说到我的最后一列是两个按钮,我尝试过用
$('table tbody button').click();
的方式,根本监听不了,最后发现要用on
,也就是// table 为之前用于初始化 DataTables 的那个,等于上文已存入 table 变量的 $('#user-list') // tbody 这个可以不要,个人习惯精确定位 // on 后面的第一个参数为事件参数,什么 touch 啊,click 啊之类 // 第二个就是重点,精确到你要监听事件的控件、标签。例如我要监听按钮就写 tr button // 第三个匿名函数没什么好说的 table.find('tbody').on('click', 'tr button', function (){ // TODO: ... var $this = $(this); // 可以拿到当前操作的对象 });
再就是所有的
API
!必须使用table.api()
调用我最开始看文档的示例:重新加载数据(ajax.reload()) 选项(option) 参考(reference) Datatables 中文网
MD!这里面根本没写api()
好吗,最后在 Google 搜索到这篇:table.ajax.reload() is undefined — DataTables forums 才解决…哎!还有…待更吧…
差点忘了中文语言:
{
"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": ": 以降序排列此列"
}
}