DataTable Notes - xsbear/dotfiles GitHub Wiki

DataTable 研究整理

基本使用

Data sources 数据源:

  • DOM(HTML tabel markup)
  • Javascript Array: js数组对象 (目前选词王选词模块使用的方式)
  • Ajax source 利用DataTable内置的ajax请求数据作为源
  • Server-side processing 服务器端分页获取数据

数据源选用要点

  • 数据源的选择根据情况而定,如果数据量小,且是模板生成的table,可以使用DOM
  • 如数据量较大,且为ajax获取,建议使用js数组,目前选词王产品中的选词模块就是使用这种方式,并且可以利用 Deferred rendering (延迟渲染)模式极大提高DT加载速度
  • Ajax source 与 js数组类似,只不过使用DT内置的ajax直接请求数据,如果应用不需要做额外ajax处理,可以使用这种方式。

常用配置选项

根据数据源、性能要求可以配置各种配置项,下面列举几个常用的选项,具体用法参看 DataTable API

  • aaData: js array 数据源数组,格式可以是二维数组 [ [a,b,c],[d,e,f] ] 或 json串数组(支持深度嵌套),后者需结合列定义的mData选项,指定目标数据

  • bDeferRender: 延迟渲染模式,开始只生成当前页所需的DOM结构,可以极大提高加载速度(适用js array 和 ajax source数据源)

  • aaSorting: 指定默认排序列,如需不需要默认排序可以指定为 []

  • bSortClasses: 排序操作时给对应列的单元格加上区分标记用的class,可以指定 false 以禁用,提高大数据量的排序操作

  • aLengthMenu,iDisplayLength,sPaginationType: 分页、页码相关配置项,较简单,可以参考官方API

  • oLanguage:语言包选项,可以分别指定各子语句翻译或赋值整个包对象(json串),也可以指定 sUrl 值通过ajax方式获取语言包文件(目前在我们的产品中,已全部改用直接赋值语言包对象,以避免一些请求被转向的异常情况)

列定义选项

列定义(column)是DataTable配置中较重要也是较复杂的配置选项,主要涉及单元数据获取、排序、过滤等选项。

列定义主要有2个参数:aoColumnDefsaoColumns ,两者基本一致,区别在于 aoColumnDefs 可以指定作用的列,而 aoColumns 需要每列逐一配置,与 table 实际列数保持一致。两者可以同时定义,但有一定优先级,具体可以看这里描述。

具体配置选项

  • mData:用于读取json对象数据源的目标属性值,或者对目标值进行预处理,如数据计算、格式化、添加包含元素等,并且可以根据不同的用途(设置值、显示、排序、过滤)分别进行处理。
	"aoColumns": [
		 { "mData": "browser" },
		 { "mData": "platform.inner" },
		 { "mData": "platform.details.0" },
	 ],
	 "aoColumnDefs": [ {
		 "aTargets": [ 0 ],
		 "mData": function ( source, type, val ) {
		   if (type === 'set') {
			source.price = val;
			// Store the computed dislay and filter values for efficiency
			source.price_display = val=="" ? "" : "$"+numberFormat(val);
			source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
			return;
		   }
		   else if (type === 'display') {
			return source.price_display;
		   }
		   else if (type === 'filter') {
			return source.price_filter;
		   }
		   // 'sort', 'type' and undefined all just use the integer
		   return source.price;
		 }
	    } ]
  • mRender:与mData基本一样,但少了改变目标值的特性,主要用于区分处理TD值的显示、过滤、排序
	"aoColumnDefs": [
	{
		"aTargets": [ 0 ],
		"mData": "download_link",
		"mRender": function ( data, type, full ) {
			return '<a href="'+data+'">Download</a>';
		}
	]
  • bSearchable, bSortable: 设置列可否过滤、排序
  • sClass: 设置列样式class

回调函数选项

  • fnInitComplete:初始化完成回调函数,可以在这里加入DT生成之后需要处理的操作,传入的参数包含 oSettings 对象
  • fnDrawCallback:每次表格重画时回调函数,包括翻页、排序、过滤都会触发此函数,可以在此加入需要处理的操作
  • fnPreDrawCallback:每次表格重画前回调函数,可以在触发翻页、排序等操作之前进行预处理

其他还有一些 DT DOM 结构重画时、或者行、列操作的回调函数,具体可以查找相关 api

事件

sort, filter 等事件,直接绑定在初始化 DataTable jquery对象上,但DataTable目前的事件机制好像不是很完善,而且在排序操作时,会同时触发 fitler 事件,作者也表示目前还没有解决,所以不建议使用事件注册,尽量使用回调函数的方式绑定操作。

常用API

  • fnSort:对某列排序
	oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
  • fnFilter:过滤,可指定特定列进行过滤
	oTable.fnFilter( 'test string',2);
  • fnGetData:返回指定位置的数据(集合),根据指定不同的dom元素(或索引)参数可以返回不同的数据值或集合数组
  • fnGetPosition 返回指定行或单元格的位置索引数组,传入的参数可以为 TR 行或 TD 单元格 DOM 元素,结合 fnGetData 可以很方便定位目标位置的数据并做相应操作
	$('#example tbody td').click( function () {
		// Get the position of the current data from the node
		var aPos = oTable.fnGetPosition( this );

		// Get the data array for this row
		var aData = oTable.fnGetData( aPos[0] );

		// Update the data array and return the value
		aData[ aPos[1] ] = 'clicked';
		this.innerHTML = 'clicked';
	} );
  • fnGetNodes:获取table所有TR或指定行的DOM节点对象
  • fnDraw 重画 DT
  • fnClearTable 清除表格(行),传参数 0 不重画table
  • fnDestroy 销毁所有DataTable相关DOM、事件、任何对原表格的更改,恢复为原始表格;传参数 1 移除原表格DOM

其他请参考 api

高级方法(DataTable 扩展)

DataTable 通过定义扩展的方式以提供个性化的高级使用方法,比如自定义排序、过滤方法、类型检测、分页类型、自定义API。

自定义排序函数(Sorting functions)

  • 基于数据类型的列排序($.fn.dataTableExt.oSort),适合静态数据
	jQuery.fn.dataTableExt.oSort['string-case-asc']  = function(x,y) {
	    return ((x < y) ? -1 : ((x > y) ?  1 : 0));
	};
  • 自定义数据源排序 ($.fn.dataTableExt.afnSortData),适合动态数据(如 input输入框等)
	jQuery.fn.dataTableExt.afnSortData['dom-text'] = function  ( oSettings, iColumn )
	{
	    var aData = [];
	    $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
		   aData.push( this.value );
	    } );
	    return aData;
	}

类型检测

详见:$.fn.dataTableExt.aTypes

分页类型

详见:$.fn.dataTableExt.oPagination

自定义过滤

与排序类似,提供基于类型 $.fn.dataTableExt.ofnSearch 和 自定义数据源 $.fn.dataTableExt.afnFiltering

DataTable 插件

DataTable 提供了一系列table增强操作的插件,包括固定表头、列宽调整、列顺序调整等,还有一些第三方插件,详见 Extra

固定表头(FixedHeader)示例

	$(document).ready( function () {
	    var oTable = $('#example').dataTable();
	    new FixedHeader( oTable );
	} );

使用技巧和注意

数据定义、配置相关建议

  • 在使用ajax获取数据的情况下,建议使用 js array 数据源,可以减少DOM渲染、模板插件调用,并提高初始化速度。大数据量下建议使用 Deferred rendering (延迟渲染) 模式。
  • 尽量不要在Table单元格(td)内包含多余DOM元素,可以为DT的过滤、排序操作提供便利,同时减少DOM节点数。
  • 尽量使用 mDatamRender 来定义需要外包元素的数据列,可以减少存储数据对象大小,并且利于排序、过滤等操作,尽管有外包元素或动态数据可以使用DataTable扩展($.fn.dataTableExt.afnSortData等)来进行排序、过滤操作。
  • 配置 "aaSorting": [] 取消默认排序,即按服务器端返回顺序排序;配置 "bSortClasses":false 禁用列排序样式,提高性能。

表格重画与事件注册、 数据修改

排序、过滤、翻页等操作的内部实现都是先移除原表格行,然后从内置数据存储对象里获取操作结果的数据集合,再重新插入到表格中,所以这些操作都会引起表格重画。如果要对table的行内元素绑定事件就要注意重画的问题,简单的使用jQuery选择器只能作用到table初始页的DOM元素,而其他页或者排序、过滤后的新表格行元素则不在注册范围内,所以也就不会触发事件。一个解决方案是通过 fnGetNodes 方法取得table的所有表格行,对其遍历逐个添加事件;但更好更快的方法是使用jQuery的 Delegate委派) 方法对在table内所有已出现或即将出现的行元素进行预注册:

	$('#cartTable').delegate('.chkbox','click',function(event){
		...
		...
	})
```
另外一个情况是,当要修改全部表格数据时,也不能仅遍历当前页的表格行元素,而是要通过 *fnGetNodes* 方法取得所有表格行元素,然后逐一遍历修改:
```javascript
	var allRows = oTable.fnGetNodes();
	var len = allRows.length;
	for (var i = 0; i < len; i ++) {
		$('td',allRows[i]).removeClass('separator');
	}
```

### 数据修改与“内存”更新
这里的“内存”指的是DataTable内置的数据存储对象,它是表格原始数据,以对象数组形式存在,并且作为排序、索引等操作的原始数据集。如果涉及对表格内数据进行修改操作,特别是input, checkbox等动态数据,就要注意修改表面数据的同时,也要修改“内存”中的数据,否则会引起排序、过滤错误(排序、过滤不启用的可以不考虑)。具体方法可以通过 *fnGetPosition* , *fnGetData* 等方法获取对应数据索引,然后赋值修改,示例可见上述 “常用API” 部分。

### 延迟渲染模式
延迟渲染(Deferred rendering)的内部原理是开始只生成第一页的表格行DOM结构,翻页或排序、过滤操作之后再按需生成DOM。此时需要注意当使用 *fnGetNodes* 时将不会得到预期的所有表格行,如果要对不在当前页的表格行进行修改,可以通过修改内存数据实现;另外如果要即时对重画后的表格进行数据操作,可以在重画回调函数( *fnDrawCallback* )中作处理。

## DataTable 文档指南
常用的API检索可访问 <http://datatables.net/ref>