datatables - 通过 ajax 将数据预加载到数组执行多个连接

datatables - preload data to array via ajax performs multiple connections

按照 教程我结束了这段代码(基本上从外部文件加载子行内容,用 JsRender 解析,到一个数组):

/* Formatting function for row details - modify as you need */
function format ( d ) {
    // `d` is the original data object for the row
    // carica il template del dettaglio
    $.ajax ({
        async: false,
        type: "POST",
        url: "incaricodetail.html",
        cache: false,
        success: function(data){
            templateHtml = data; 
        }
    });
    var template = $.templates(templateHtml);
    var htmlOutput = template.render(d);

    return htmlOutput;
}

$(document).ready(function() {

    $.fn.dataTable.moment( 'DD/MM/YYYY' ); 
    var dettagli = []; 
    var table = $('#tabellaDati').DataTable( {
        "data": <?= json_encode($stmt->fetchAll(PDO::FETCH_ASSOC));?>,  
        "columns": [
            {
                "className":      'details-control',
                "orderable":      false,
                "data":           null,
                "defaultContent":
                    '<a class="btn btn-xs" href="incarico_edit.php?id=<?=$id;?>&pageFrom=<?=pathinfo($_SERVER['PHP_SELF'], PATHINFO_FILENAME ); ?>" title="Modifica"><span class="glyphicon glyphicon-edit"></span></a>'+
                    '<a class="btn btn-xs delete-object" href="delete.php?id=<?=$row["id"]?>" delete-id="{$id}"" title="Elimina"><span class="glyphicon glyphicon-trash"></span></a>'+
                    '<a class="btn btn-xs" href="#" id="mostraDettaglio" title="dettaglio"><span class="glyphicon glyphicon-plus"></span></a>',
                    "render": function(data, type, row, meta) {
                        dettagli[meta.row] = format(data);
                    }

           },
           { "data": "id" },
           { "data": "protocollo" },
           { 
              "data": "dataIncarico",
              "type": "date",
              "dateFormat": "dd-mm-yyyy"
           }

        ],
        "order": [[1, 'asc']]
    });

    // Add event listener for opening and closing details
    $('#tabellaDati tbody #mostraDettaglio').on('click', function () {
        var tr = $(this).closest('tr');
        var row = table.row( tr );

        if ( row.child.isShown() ) {
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
        }
        else {
            // Open this row
            row.child(dettagli[row.index()]).show();
            tr.addClass('shown');
        }
    } );
} );

我不知道为什么,但是对文件 incaricodetail.html 的 ajax 调用执行了三次(例如,对于两条记录,我有 6 个 POST 连接)。

DataTables 调试器代码:onucak

为什么会这样? 亚历克斯

初始化后,render 被多次调用:

  • 显示
  • 排序
  • 过滤器
  • 类型(检测)

那是 每行 !您可以通过 type 参数检查渲染调用的类型。一个合格的猜测是你的渲染函数是在 typedisplayfilter 上调用的——你有 2 行,它对 format() 函数进行了 6 次调用,然后6 POST 个连接,因为您已关闭 cache

您可以简单地避免这种情况:

render: function(data, type, row, meta) {
   if (typeof dettagli[meta.row] == 'undefined') {
      dettagli[meta.row] = format(data);
   }
}

为什么使用不同的 type 多次调用 render?
所以你可以 return 不同的数据用于不同的目的。假设你有一些 HTML 包含一个复选框作为显示,对于排序你可以传递 0,对于过滤你可以传递是/否,对于类型你可以传递数字。


更新。在 initComplete() 中初始化 dettagli[] 而不是 render() :

var table = $('#example').DataTable({
    initComplete : function() {
        var api = this.api(),
            rowCount = api.data().length;
        for (var i=0;i<rowCount;i++) {
            dettagli[i] = format(api.row(i).data()[0]);
        }    
    }        
});

这应该与 dettagli[meta.row] = format(data); 相同,即调用 format() 每行的第 0 列内容。

您还应该考虑只加载 incaricodetail.html 一次。为什么每次都加载它? incaricodetail.html的内容好像没有改的意思,所以

var template;
$.get("incaricodetail.html", function(html) {
   template = $.templates(html);
});

function format ( d ) {
   return template.render(d);
}

不完全一样吗?