jQuery 高效的连续.append()用法

示例

开始:

的HTML

<table id='my-table' width='960' height='500'></table>

JS

var data = [
    { type: "Name", content: "John Doe" },
    { type: "Birthdate", content: "01/01/1970" },
    { type: "Salary", content: "$40,000,000" },
    // ...另外300行...
    { type: "Favorite Flavour", content: "Sour" }
];

在循环内附加

您刚刚收到了大量数据。现在是时候遍历并在页面上呈现它了。

您首先想到的是做这样的事情:

var i;                        // <- the current item number
var count = data.length;      // <- the total
var row;                      // <- for holding a reference to our row object

// 遍历数组
for ( i = 0; i < count; ++i ) {
    row = data[ i ];

    // 将整行放入桌子
    $('#my-table').append(
        $('<tr></tr>').append(
            $('<td></td>').html(row.type),
            $('<td></td>').html(row.content)
        )
    );
}

这是完全有效的,并且将完全呈现您的期望,但是...

不要这样做。

还记得那300多行数据吗?

每个元素都会迫使浏览器重新计算每个元素的宽度,高度和位置值,以及其他任何样式-除非它们被布局边界所分隔,不幸的是,在此示例中(因为它们是<table>元素的后代),它们不能。

如果数量少而且色谱柱数少,那么这种性能损失肯定可以忽略不计。但是我们希望每一毫秒都可以计数。


更好的选择

  1. 添加到单独的数组,在循环完成后追加

/** 
 * 重复的 DOM 遍历(沿着元素树向下,直到达到
 * 你要找的-比如我们的<table>)也应该尽量避免。
 */

// 将表缓存在变量中,然后使用它,直到您认为它已被删除为止
var $myTable = $('#my-table');

// To hold our new <tr> jQuery objects
var rowElements = [];

var count = data.length;
var i;
var row;

// 遍历数组
for ( i = 0; i < count; ++i ) {
    rowElements.push(
        $('<tr></tr>').append(
            $('<td></td>').html(row.type),
            $('<td></td>').html(row.content)
        )
    );
}

// 最后,一次插入所有行
$myTable.append(rowElements);

在这些选项中,这一选项最依赖jQuery。


  1. 使用现代的Array。*方法

var $myTable = $('#my-table');

// 使用.map()方法循环
//  -这将根据回调函数的结果为我们提供一个全新的数组
var rowElements = data.map(function ( row ) {

    // 创建一行
    var $row = $('<tr></tr>');

    // 创建列
    var $type = $('<td></td>').html(row.type);
    var $content = $('<td></td>').html(row.content);

    // 将列添加到行
    $row.append($type, $content);
    
    // 添加到新生成的数组
    return $row;
});

// 最后,将所有行放入表中
$myTable.append(rowElements);

在功能上等同于之前的版本,仅易于阅读。


  1. 使用HTML字符串(而不是jQuery内置方法)

// ...
var rowElements = data.map(function ( row ) {
    var rowHTML = '<tr><td>';
    rowHTML += row.type;
    rowHTML += '</td><td>';
    rowHTML += row.content;
    rowHTML += '</td></tr>';
    return rowHTML;
});

// 在这里使用.join('')将所有单独的字符串合并为一个
$myTable.append(rowElements.join(''));

完全有效,但是不建议再次使用。这迫使jQuery立即解析大量文本,这是不必要的。正确使用时,jQuery非常擅长做什么。


  1. 手动创建元素,追加到文档片段

var $myTable = $(document.getElementById('my-table'));

/**
 * 创建一个文档片段来保存我们的列
 * - 把这个添加到每一行后,它就会自动清空
 *   所以我们可以在下一次迭代中重用它。
 */
var colFragment = document.createDocumentFragment();

/**
 * 这次使用. reduce ()对数组进行循环。 
 * 我们得到了一个很好的,整齐的输出,没有任何副作用。
 *  - 在本例中,结果将是
 *    包含所有<tr>元素的文档片段。
 */
var rowFragment = data.reduce(function ( fragment, row ) {

    // 创建一行
    var rowEl = document.createElement('tr');

    // 创建列 and the inner text nodes
    var typeEl = document.createElement('td');
    var typeText = document.createTextNode(row.type);
    typeEl.appendChild(typeText);

    var contentEl = document.createElement('td');
    var contentText = document.createTextNode(row.content);
    contentEl.appendChild(contentText);

    // 将列添加到列片段
    // -如果分别迭代列,这将很有用
    //   但在此示例中,仅用于展示和讲述。
    colFragment.appendChild(typeEl);
    colFragment.appendChild(contentEl);
    
    rowEl.appendChild(colFragment);

    // 将rowEl添加到片段-这充当临时缓冲区 
    // 批量插入之前累积多个DOM节点
    fragment.appendChild(rowEl);

    return fragment;
}, document.createDocumentFragment());

// 现在将整个片段转储到您的表中
$myTable.append(rowFragment);

我个人的最爱。这说明了jQuery在较低级别上的用途的一般概念。