jQuery 使用大量数据更新 DOM 时页面冻结
jQuery page freezing while updating DOM with big amount of data
我有一个 jQuery post 方法,它看起来像这样:
$.post("/SearchCompetitor/Index", { username: _username }, StartLoading())
.done(function (data) {
if (data !== "UsernameError") {
StopLoading();
var brands = $('<table />').append(data).find('#tableProducts').html();
$('#tableProducts').html(brands);
$("#tableProducts").simplePagination({
// the number of rows to show per page
perPage: 10,
// CSS classes to custom the pagination
containerClass: '',
previousButtonClass: '',
nextButtonClass: '',
// text for next and prev buttons
previousButtonText: 'Previous',
nextButtonText: 'Next',
// initial page
currentPage: 1
});
var header = $('<div />').append(data).find('.bs-glyphicons').html();
$('.bs-glyphicons').html(header);
$('#tableProducts thead, #header').fadeIn("slow");
$('#emptyText').hide();
}
else {
StopLoading();
ShowMessage("No eBay user was found under: " + $('.txtSearch').val());
}
})
.fail(function (data) {
StopLoading();
ShowMessage("Something went wrong, please try again!");
});
当 post 数据对象内部不包含很多项目时,它还不错,加载时没有问题...
但是当我用里面的 2000 多个项目更新 table 时,它出现了一个大问题,我在 firefox 浏览器上测试它,每次我处理 2000 多个返回的项目时它都会崩溃。 ..
我的问题是,有没有什么方法可以避免浏览器冻结,也许某些 "client side async method" 就像 C# 在使用异步方法时防止用户 UI 在处理大块数据时冻结一样? ?
正如我在评论中提到的,减少您注入 DOM 的记录数量可能是首先要解决的问题(谁真的想要一个显示 2000 多条记录的网页) .使用分页(正如您所说的那样)将大大有助于解决问题。
其次,要非常小心 DOM 注入点 - 尽量减少修改 DOM 的频率,因为这是一个众所周知的瓶颈。
减少 DOM 注入的一种非常有效的方法是使用字符串数据并操作字符串,直到它准备好在 DOM 中使用。只有在那个时候你才会注射它。此外,切勿在循环中注入 DOM。
所以,我在您的代码中看到的经过仔细审查的是:
StartLoading() // <-- you are invoking the function with this code
这应该是函数引用,而不是函数调用,所以该行应该是:
$.post("/SearchCompetitor/Index", { username: _username }, StartLoading)
接下来,我们有这个:
var brands = $('<table />').append(data).find('#tableProducts').html();
$('#tableProducts').html(brands);
首先,您将 AJAX 结果直接附加到 DOM 中,然后搜索您刚刚附加的内容(搜索 DOM)#tableProducs
。我建议您在 data
中搜索您需要的内容,然后再将其添加到 DOM:
// Find what you need without injecting it into the DOM so you don't
// have to search the DOM for it:
var brands = $(data).find('#tableProducts').html();
// Just append what you need when you need it:
$('<table />').append(brands);
你稍后在你的代码中有同样的场景:
var header = $('<div />').append(data).find('.bs-glyphicons').html();
再次,在将其注入 DOM 之前搜索 data
以查找您需要的内容。
最后,考虑您应该使用 .html()
还是 .text()
。前者导致内容被 HTML 解析器解析,而后者则不会。如果内容包含标记,是的,你会想要 .html()
,但如果没有,.text()
会更快。
我在使用 ajax 调用更新包含 1000 多个 DIV 元素的元素时遇到了类似的问题:仅用 300 DIVS 替换它会冻结浏览器。
有趣的是,问题似乎不在于获取的元素数量,而在于覆盖元素。我通过先清空元素来解决它,就像你的情况一样
$('#tableProducts').html('');
$('#tableProducts').html(brands);
我有一个 jQuery post 方法,它看起来像这样:
$.post("/SearchCompetitor/Index", { username: _username }, StartLoading())
.done(function (data) {
if (data !== "UsernameError") {
StopLoading();
var brands = $('<table />').append(data).find('#tableProducts').html();
$('#tableProducts').html(brands);
$("#tableProducts").simplePagination({
// the number of rows to show per page
perPage: 10,
// CSS classes to custom the pagination
containerClass: '',
previousButtonClass: '',
nextButtonClass: '',
// text for next and prev buttons
previousButtonText: 'Previous',
nextButtonText: 'Next',
// initial page
currentPage: 1
});
var header = $('<div />').append(data).find('.bs-glyphicons').html();
$('.bs-glyphicons').html(header);
$('#tableProducts thead, #header').fadeIn("slow");
$('#emptyText').hide();
}
else {
StopLoading();
ShowMessage("No eBay user was found under: " + $('.txtSearch').val());
}
})
.fail(function (data) {
StopLoading();
ShowMessage("Something went wrong, please try again!");
});
当 post 数据对象内部不包含很多项目时,它还不错,加载时没有问题...
但是当我用里面的 2000 多个项目更新 table 时,它出现了一个大问题,我在 firefox 浏览器上测试它,每次我处理 2000 多个返回的项目时它都会崩溃。 ..
我的问题是,有没有什么方法可以避免浏览器冻结,也许某些 "client side async method" 就像 C# 在使用异步方法时防止用户 UI 在处理大块数据时冻结一样? ?
正如我在评论中提到的,减少您注入 DOM 的记录数量可能是首先要解决的问题(谁真的想要一个显示 2000 多条记录的网页) .使用分页(正如您所说的那样)将大大有助于解决问题。
其次,要非常小心 DOM 注入点 - 尽量减少修改 DOM 的频率,因为这是一个众所周知的瓶颈。
减少 DOM 注入的一种非常有效的方法是使用字符串数据并操作字符串,直到它准备好在 DOM 中使用。只有在那个时候你才会注射它。此外,切勿在循环中注入 DOM。
所以,我在您的代码中看到的经过仔细审查的是:
StartLoading() // <-- you are invoking the function with this code
这应该是函数引用,而不是函数调用,所以该行应该是:
$.post("/SearchCompetitor/Index", { username: _username }, StartLoading)
接下来,我们有这个:
var brands = $('<table />').append(data).find('#tableProducts').html();
$('#tableProducts').html(brands);
首先,您将 AJAX 结果直接附加到 DOM 中,然后搜索您刚刚附加的内容(搜索 DOM)#tableProducs
。我建议您在 data
中搜索您需要的内容,然后再将其添加到 DOM:
// Find what you need without injecting it into the DOM so you don't
// have to search the DOM for it:
var brands = $(data).find('#tableProducts').html();
// Just append what you need when you need it:
$('<table />').append(brands);
你稍后在你的代码中有同样的场景:
var header = $('<div />').append(data).find('.bs-glyphicons').html();
再次,在将其注入 DOM 之前搜索 data
以查找您需要的内容。
最后,考虑您应该使用 .html()
还是 .text()
。前者导致内容被 HTML 解析器解析,而后者则不会。如果内容包含标记,是的,你会想要 .html()
,但如果没有,.text()
会更快。
我在使用 ajax 调用更新包含 1000 多个 DIV 元素的元素时遇到了类似的问题:仅用 300 DIVS 替换它会冻结浏览器。
有趣的是,问题似乎不在于获取的元素数量,而在于覆盖元素。我通过先清空元素来解决它,就像你的情况一样
$('#tableProducts').html('');
$('#tableProducts').html(brands);