perf(website): cache sort values and batch DOM appends in sortRows

Calling getSortValue inside the comparator ran DOM queries on every
comparison (O(n log n) reads). Hoisting into a forEach beforehand reduces
that to O(n). Batching row appends through a DocumentFragment also avoids
repeated reflows during table reorder.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Vinta Chen
2026-03-22 01:32:21 +08:00
parent d36f1ed8d1
commit 3d9c2ae507
+18 -11
View File
@@ -143,29 +143,36 @@ function getSortValue(row, col) {
function sortRows() { function sortRows() {
var arr = Array.prototype.slice.call(rows); var arr = Array.prototype.slice.call(rows);
if (activeSort) { var col = activeSort.col;
var order = activeSort.order;
// Cache sort values once to avoid DOM queries per comparison
arr.forEach(function (row) {
row._sortVal = getSortValue(row, col);
});
arr.sort(function (a, b) { arr.sort(function (a, b) {
var aVal = getSortValue(a, activeSort.col); var aVal = a._sortVal;
var bVal = getSortValue(b, activeSort.col); var bVal = b._sortVal;
if (activeSort.col === 'name') { if (col === 'name') {
var cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0; var cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
if (cmp === 0) return a._origIndex - b._origIndex; if (cmp === 0) return a._origIndex - b._origIndex;
return activeSort.order === 'desc' ? -cmp : cmp; return order === 'desc' ? -cmp : cmp;
} }
if (aVal <= 0 && bVal <= 0) return a._origIndex - b._origIndex; if (aVal <= 0 && bVal <= 0) return a._origIndex - b._origIndex;
if (aVal <= 0) return 1; if (aVal <= 0) return 1;
if (bVal <= 0) return -1; if (bVal <= 0) return -1;
var cmp = aVal - bVal; var cmp = aVal - bVal;
if (cmp === 0) return a._origIndex - b._origIndex; if (cmp === 0) return a._origIndex - b._origIndex;
return activeSort.order === 'desc' ? -cmp : cmp; return order === 'desc' ? -cmp : cmp;
}); });
} else {
arr.sort(function (a, b) { return a._origIndex - b._origIndex; }); var frag = document.createDocumentFragment();
}
arr.forEach(function (row) { arr.forEach(function (row) {
tbody.appendChild(row); frag.appendChild(row);
tbody.appendChild(row._expandRow); frag.appendChild(row._expandRow);
}); });
tbody.appendChild(frag);
applyFilters(); applyFilters();
} }