高效的連續 .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 more rows...
{ 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
// Loop over the array
for ( i = 0; i < count; ++i ) {
row = data[ i ];
// Put the whole row into your table
$('#my-table').append(
$('<tr></tr>').append(
$('<td></td>').html(row.type),
$('<td></td>').html(row.content)
)
);
}
這是完全有效的,將完全呈現你的期望,但……
不要這樣做
還記得 300 多行資料嗎?
每一個都會強制瀏覽器重新計算每個元素的寬度,高度和定位值,以及任何其他樣式 - 除非它們被佈局邊界分開,不幸的是,這個例子(因為它們是 <table>
元素的後代),他們不能。
在少量和少量列的情況下,這種效能損失肯定可以忽略不計。但我們希望每毫秒都能計算出來。
更好的選擇
-
新增到單獨的陣列,在迴圈完成後追加
/**
* Repeated DOM traversal (following the tree of elements down until you reach
* what you're looking for - like our <table>) should also be avoided wherever possible.
*/
// Keep the table cached in a variable then use it until you think it's been removed
var $myTable = $('#my-table');
// To hold our new <tr> jQuery objects
var rowElements = [];
var count = data.length;
var i;
var row;
// Loop over the array
for ( i = 0; i < count; ++i ) {
rowElements.push(
$('<tr></tr>').append(
$('<td></td>').html(row.type),
$('<td></td>').html(row.content)
)
);
}
// Finally, insert ALL rows at once
$myTable.append(rowElements);
在這些選項中,這個選項最依賴於 jQuery。
-
使用現代 Array。*方法
var $myTable = $('#my-table');
// Looping with the .map() method
// - This will give us a brand new array based on the result of our callback function
var rowElements = data.map(function ( row ) {
// Create a row
var $row = $('<tr></tr>');
// Create the columns
var $type = $('<td></td>').html(row.type);
var $content = $('<td></td>').html(row.content);
// Add the columns to the row
$row.append($type, $content);
// Add to the newly-generated array
return $row;
});
// Finally, put ALL of the rows into your table
$myTable.append(rowElements);
功能上與之前的相同,只是更容易閱讀。
-
使用 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;
});
// Using .join('') here combines all the separate strings into one
$myTable.append(rowElements.join(''));
*完全有效,*但再次,不推薦。這迫使 jQuery 一次解析大量文字而不是必需的。jQuery 非常擅長正確使用時的功能。
-
手動建立元素,附加到文件片段
var $myTable = $(document.getElementById('my-table'));
/**
* Create a document fragment to hold our columns
* - after appending this to each row, it empties itself
* so we can re-use it in the next iteration.
*/
var colFragment = document.createDocumentFragment();
/**
* Loop over the array using .reduce() this time.
* We get a nice, tidy output without any side-effects.
* - In this example, the result will be a
* document fragment holding all the <tr> elements.
*/
var rowFragment = data.reduce(function ( fragment, row ) {
// Create a row
var rowEl = document.createElement('tr');
// Create the columns 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);
// Add the columns to the column fragment
// - this would be useful if columns were iterated over separately
// but in this example it's just for show and tell.
colFragment.appendChild(typeEl);
colFragment.appendChild(contentEl);
rowEl.appendChild(colFragment);
// Add rowEl to fragment - this acts as a temporary buffer to
// accumulate multiple DOM nodes before bulk insertion
fragment.appendChild(rowEl);
return fragment;
}, document.createDocumentFragment());
// Now dump the whole fragment into your table
$myTable.append(rowFragment);
我個人的最愛。這說明了 jQuery 在較低階別執行的操作的一般概念。