动态枚举排序
数据的排序是交互式表格中至关重要的一面,是 DataTables 核心所在,让终端用户可以轻松地查找到他们正在寻找的数据。DataTables 针对数字、货币、日期和字符串,内置多种排序类型,但数据是复杂的,DataTables 无法为所有数据集定义排序选项。因此,它提供一个 插件接口,可以让您为数据自定义排序规则。
在这篇文章中,我将介绍一个功能,它将为 枚举列表(通常缩写为 枚举)动态创建排序和类型检测插件。
这个简单的示例表格演示了使用插件直观地对优先级列进行排序
项目名称 | 优先级 |
---|---|
Skilled Drill | 高 |
Yellow Sleepy Uranium | 低 |
Massive Tungsten | 中 |
Dusty Scissors | 高 |
大院 | 低 |
Moving Backpack | 低 |
Risky Cloud | 中 |
为什么对枚举进行排序?
表格中所示数据最终可能只是字符串,但这些字符串传达了大量我们直观理解的信息。例如,如果我们考虑以下三个数据点
- 高
- 中
- 低
我们直观地看到了与它们相关联的优先级顺序。然而,如果它们作为字符串排序,则会被显示为:高、低、中,这种方式会令终端用户困惑。使用枚举排序插件,我们可以告诉 DataTables 我们希望如何对数据排序。
动态解决方案的需求
编写一个能处理已知枚举和硬编码排序值的插件(比如 "高" = 1
、"中" = 2
等)很简单,但是我们总是遵循 不要重复自己 (DRY) 原则,以保持代码简洁、干净且易于管理,因此我们需要一个接受开发人员所需的任何枚举的插件。
因此,我们的软件的目标是使用一个函数,它将接受一个值数组,分别定义枚举中的值及其顺序(升序 - 降序由 DataTables 自动处理)
DataTable.enum( [ ... ] );
映射
在深入了解代码之前,我们首先考虑如何实现排序和类型检测插件。本质上,我们只需要检查数据点是否在源数组中,如果在,则检查其位置。我们可以使用 Array.prototype.indexOf
或 jQuery 的 $.inArray
来支持较旧的浏览器,但这不可避免地会导致对阵列数据进行循环,这会损害性能。
相反,我们可以创建一个反向映射对象,其中值为属性键,以实现快速查找,属性值为索引。考虑我们的示例 [ '高', '中', '低' ]
- 它将变成
{
"High": 0,
"Medium": 1,
"Low": 2
}
此方法的缺点是,在 ES5 中,对象键只能是字符串 - 因此,如果您使用的是无法轻松转换为唯一字符串(.toString()
)的复杂对象,则可能遇到冲突。 ES6 引入了 Map
对象,旨在应对这种情况。
现代浏览器具有 相当好的 Map
支持,但当然并非我们所有的客户都使用了新版浏览器,因此我们需要根据需要回退到对象。
我们的映射代码因此十分简单,如下所示
var lookup = window.Map ? new Map() : {};
for ( var i=0, ien=arr.length ; i<ien ; i++ ) {
lookup[ arr[i] ] = i;
}
插件
有了现有的查找映射表,我们现在可以创建针对 DataTables 类型的检测和排序插件。
类型检测
DataTables 的 类型检测插件 附加到了 DataTable.ext.type.detect
数组。这是一个函数数组,DataTables 将遍历此数组,检查列中的数据是否与任何给定的类型匹配。
在我们的案例中,我们只需检查查找对象是否包含 DataTables 正在检查的数据点的任何值即可。
DataTable.ext.type.detect.unshift( function ( d ) {
return lookup[ d ] !== undefined ?
name :
null;
} );
请注意,unshift
用于将类型检测函数的前缀添加到数组的开头,以确保 DataTables 在其他函数之前使用此类型检测。
此外,请注意变量 name
的用法,它为此数据类型提供了独特的名称。它只是一个带有前缀 enum-
的计数器,以确保可以在一个页面上使用多个枚举!
排序插件
排序插件 附加到 DataTable.ext.type.order
对象,使用排序方法将应用到的 type 的名称。DataTables 内置了针对数字和字符串值的排序比较,因此我们所需要做的就是创建一个会返回可排序值的插件,在这种情况中为查找对象中已有的数据点的数组索引
DataTable.ext.type.order[ name+'-pre' ] = function ( d ) {
return lookup[ d ];
};
将所有内容放在一起
结果就是我们拥有了一个十分简单但用途广泛的插件,该插件可按任何顺序对任何数据进行排序
var unique = 0;
DataTable.enum = function ( arr ) {
var name = 'enum-'+(unique++);
var types = DataTable.ext.type;
var lookup = {};
for ( var i=0, ien=arr.length ; i<ien ; i++ ) {
lookup[ arr[i] ] = i;
}
// Add type detection
types.detect.unshift( function ( d ) {
return lookup[ d ] !== undefined ?
name :
null;
} );
// Add sorting method
types.order[ name+'-pre' ] = function ( d ) {
return lookup[ d ];
};
};
只需复制代码从上面复制即可使用此插件,或者你可以直接从 DataTales CDN 包含此插件。
反馈
一如既往,我们非常欢迎反馈。如果你看到可以改进的地方,请随意发起新的 论坛讨论 或派生 DataTables 插件 repo 并发送包含你所做的更改的拉取请求。