加速 Ajax 成功的 DOM 操作
Speeding up Ajax success DOM manipulation
我在我的页面上使用了 AJAX 调用,该调用返回表行,并在成功后将它们添加到页面中的表中。以下是当前使用的代码:
function GetDPRecords(Perso) {
//alert(Perso);
$Records = $('#DPRecords');
//alert($PersoFileName.val()+" | "+$ProcFromDate.val()+" | "+$ProcToDate.val());
$.ajax({
type: "GET",
url: "SelectDPRecords.jsp",
data: $('form#Search_Form').serialize() + "&Personalized=" + Perso,
beforeSend: function () {
$Records.find("tr:gt(0)").remove();
$("<tr><td colspan='4'><h3 style='margin: 4px 10px'> Loading... </h3></td></tr>").hide().appendTo($Records).show(400);
},
success: function (data) {
$Records.find("tr:gt(0)").remove();
$(data).hide().appendTo($Records).show(400);
}
});
}
问题是我有时期望返回大量行(1,000-5,000)。我用返回的 4,000 行数据进行了测试运行,它导致浏览器在大约 20 秒内无响应。
有什么方法可以优化代码并减少加载时间吗?
一种可能的解决方案是使用分页系统:不是返回 1,000-5,000 行,而是将结果分成每页 50 个结果的页面,并且一次只返回一页。然后,您将为用户提供按钮以在表格的顶部/底部加载其他页面。
有关我正在谈论的示例,请参阅 http://luis-almeida.github.io/jPages/defaults.html。它使用图片而不是行,但它是相同的基本概念。
只是为了添加@aj_r的建议 如果您不想再次访问服务器来检索下一个范围的数据,则可以将结果存储到 javascript 变量(JSON 对象数组)中,然后在本地使用它进行分页。
我最近在jqGrid中使用巨大的数据网格时遇到了同样的问题,并且我已经能够找到一个棘手的解决方案,结果证明它运行良好。
问题是你不能一次渲染所有这些数据 - 这太多了,特别是考虑到 DOM 操作有多慢。所以你需要某种队列。您可以将这些数据拆分为块,并使用setTimeout()
或setInterval()
按顺序呈现它们,但这些块在性能方面也没有很好的声誉。
我最终使用了reuestAnimationFrame,并将我的大量数据分成几部分,并在动画帧可用时渲染它们。所以你需要从 polyfill 开始,以确保你要做的事情真的有效,我正在使用 Paul Irish 的一个很棒的:
这里有一个可怕的jsFiddle:http://jsfiddle.net/cjw5eota/1/
这是JS:
var dataRows = 5000; // enter ammount of returned rows
var chunkSize = 200; // define single chunk size, optimize for best performance bu trying different values, if your DOM manipulation is heavy use less, if its lightweight you can use more, use 1 to see in slowmo how it works
// We are simulating big returned object here
var data = {}
for (var i = 0; i < dataRows; i++) {
data[i] = {
'id': i,
'name': 'I am data for row ' + i
};
}
// shim layer with setTimeout fallback
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function renderRecords(data) {
var dataLength = Object.keys(data).length;
var i = 0;
function renderInQueue() {
console.time('Rendering in queue');
for (t = 0; t < chunkSize; t++) {
if (i < dataLength) {
var row = '<tr><td>' + data[i].id +
'</td><td>' + data[i].name + '</td></tr>'
$('table').append(row);
}
i++;
}
if (i < dataLength) {
requestAnimationFrame(renderInQueue);
} else {
console.log('Done rendering');
console.timeEnd('Rendering in queue');
}
}
renderInQueue();
}
// run the script of rendering
renderRecords(data);
我提供了一个简单的性能基准测试,供您在控制台中查看整个渲染过程需要多少时间。使用chunkSize
看看它是如何变化的,并尝试找到最适合您需求的值,即在不给浏览器带来沉重负担的情况下为您提供体面的渲染时间。
您尝试一次渲染的次数越多,渲染速度就越快,但处理每次渲染迭代需要更多的资源。
- AngularJS-独立的控制器和DOM操作
- casper.waitForSelector无法处理动态DOM操作
- 页面加载后的 Dojo DOM 操作
- 我应该只在指令的链接 fn 中进行 DOM 操作吗?
- 将 DOM 操作与 Angular 控制器分离 - 需要最佳实践
- 文本内容长度在 DOM 操作后不会更改
- DOM 操作、向后兼容性和跨浏览器问题
- 为什么我需要使用 document.write 而不是 DOM 操作方法
- "撤消”;Javascript中的DOM操作函数
- JavaScript中面向对象DOM操作的混乱混乱
- 使用循环来简化DOM操作VanillaJS
- JavaScript-所有DOM操作函数都返回null/empty
- 浏览器使用Java而不是Javascript作为DOM操作语言
- DOMNodeInserted在对主体执行DOM操作时表现得很奇怪
- 使用 jQuery 或 AngularJS 的 DOM 操作和选择
- DOM 操作以重现订单列表
- 使用 PhantomJS 的 DOM 操作
- 如何在 AngularJS 中同时处理 DOM 操作和状态更改
- 如何使用Javascript在UL-LI块中进行简单的DOM操作
- 角度指令 DOM 操作行为