API 插件开发

DataTable 的 API 提供许多 方法,这些方法能用于处理表格并从中收集数据。所需的大量方法均已内置,不过你可能也会发现自己需要创建插件 API 方法来扩展内置的功能。本页面探讨如何为 DataTables 创建插件 API 方法。

在详细介绍如何创建插件方法之前,应该考虑创建何种插件可能更有用

  • 使用标准 API 执行常见操作的快捷方式(将多个调用缩短为单个方法)
  • 数据摘要方法(求和、平均值、标准差等)
  • 功能插件 的表格处理。

DataTables API

在为 DataTables 创建新的 API 方法之前,了解 API 的基本原理 非常重要,特别是链式操作的概念(由于方法会返回自身的实例,因此可以直接在第一个方法的结果中调用其他方法)及其结果设置。

DataTables API 实例就像数组,因为它看起来极像 Javascript 数组并且有许多相同的方法和属性(例如,.length)- 数组的内容便是该“结果设置”。值得注意的是,从技术层面来讲,API 不完全是数组,只是非常类似,这与 jQuery 类似,你可以在其中使用数组语法访问节点。

实例的结果设置可以是空数组、行、列或单元格索引数组、数据对象或其他任何内容。将会在结果设置中遇到所有类型的数据,其包含内容会极大地取决于你自身的方法。

执行范围

插件 API 方法会在 API 实例的范围内执行 - 例如,this.rows() 会调用 rows() 方法。因此,除了希望执行的 JavaScript 数据和 DOM 处理操作之外,一整套内置的 API 可供自己的方法使用。

此外,API 实例应操作的表格存储在 this.context 参数中。context 参数是 DataTables 设置对象(针对每张表格都是唯一的)的数组 - 它必须是数组,因为 API 是支持多张表格的,并且方法应操作 context 引用的所有表格。

注册新方法

使用 DataTable.Api.register() 静态方法可以注册新的 API 方法。它需要两个参数并且没有返回值

  • 输入参数
    • 方法名称
    • 方法函数

该方法名称是完整的链式表达式)。例如,要添加 rows().sum() 方法,您可以使用该完整字符串 (rows().sum())。sum() 方法仅对 rows() 方法(将由 DataTables API 处理器自动添加)的结果可用。还要将 sum() 视为“顶级方法”,它对任何 API 实例可用,与它的链无关。

该方法函数是描述插件逻辑的 function。如上所述,它在 API 实例的作用域内执行。此外,它可以返回任何值(包括用于链接的实例,如果没有预期其他返回值),并且将接受您的方法所需的任何参数。

示例

让我们考虑两个示例来说明这些要点。第一个 sum() 将成为一个顶级方法,它将简单地对结果集中的数据求和并返回它。第二个将附加到 rows() 方法,并提供向选中行添加类别的能力。它将返回用于链的实例。

sum()

sum() 方法实际上非常简单 - 我们循环遍历结果集中的数据,简单地全部相加并返回该值。最终结果是,我们有一个方法,当结果集包含数字数据时,可以使用该方法对数字数据求和 - 例如,从对 columns().data() 的调用。

DataTable.Api.register( 'sum()', function () {
    var sum = 0;

    for ( var i=0, ien=this.length ; i<ien ; i++ ) {
        sum += this[i];
    }

    return sum;
} );

示例调用

  • table.column( 2 ).data().sum();
  • `table.cells( '.selected', 3 ).data().sum();

rows().addClass()

此示例更加复杂,因为我们需要考虑 API 的多表特性。需要执行的是,我们循环遍历 API 中的每个上下文(即每个表),并对每个上下文的行也进行循环遍历,并在需要时添加类别。

这是最完整的代码

DataTable.Api.register( 'rows().addClass()', function ( klass ) {
    var context = this.context;

    for ( var i=0, ien=this.length ; i<ien ; i++ ) {
        var innerApi = new DataTable.Api( context[i] );

        for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
            var node = innerApi.row( this[i][j] ).node();
            $(node).addClass( klass );
        }
    }

    return this;
} );

请注意,rows() 将使用数组数组填充结果集!每个表有一个内部数组,并且每个内部数组包含该表的索引。在上面的代码中,这意味着 this.context.length === this.length (即,结果集中针对每个表有一个项目)。

由于在以下形式中循环遍历多个表在 API 中很常见,因此 DataTables 提供一个 iterator 方法来简化该操作。 iterator 会在内部处理双重 for 循环(和其他类型的循环),并向闭包函数提供有关循环的信息。上面的代码可以简化为

DataTable.Api.register( 'rows().addClass()', function ( klass ) {
    return this.iterator( 'row', function ( context, index ) {
        var node = new DataTable.Api( context ).row( index ).node();
        $(node).addClass( klass );
    } );
} );

DataTables 1.10.3 中,可以进一步简化,因为针对 iterator 的回调方法在 API 实例的作用域中执行,该实例仅在其上下文中包含有问题的表

DataTable.Api.register( 'rows().addClass()', function ( klass ) {
    return this.iterator( 'row', function ( context, index ) {
        var node = this.row( index ).node();
        $(node).addClass( klass );
    } );
} );