【问题标题】:jQuery .prependTo() created table causing browser to "lag"jQuery .prependTo() 创建表导致浏览器“滞后”
【发布时间】:2014-03-19 14:43:28
【问题描述】:

我有一个无法解决的问题,很难解释,但我会尽力而为。

基本上我已经创建了一个 Web 应用程序(在 CodeIgniter 中),它获取来自 json 编码 的数组的一些数据,并通过使用 成功函数中的jQuery .prependTo() 方法。

表格的每一行都包含来自数据库的不同元素(来自 json),具体取决于 i 计数器的值。

代码如下(我剪掉了<tr><td>内容的部分,只是样式)

$.ajax({
type: "get",
async: false,
....
....
success: function(data) {


                    var i;
                    var item_cost = new Array();
                    var item_name = new Array();
                    var item_code = new Array();
                    var item_interno = new Array();

                    for(i = 0; i < data.length; i++) {
                       item_cost[i] = data[i].cost;
                       item_name[i] = data[i].name;
                       item_code[i] = data[i].code;
                       item_interno[i] = data[i].codiceinterno;


                       var newTr = // creates the <tr>
                       newTr.html('//creates the <td>')
                       newTr.prependTo("#myTable");
                    }
},

很抱歉,如果有点不清楚,如果您需要我更新代码,因为我错过了一些重要的事情,请告诉我,我会这样做,但仅此代码就可以解释我的问题。

如果数据库中的行数很少(例如,i = 300),则应用程序运行良好。它们被正确显示和渲染,我没有得到任何浏览器减慢过程。但是当我使用 i = 4000 行时,浏览器开始运行缓慢,就像 Javascript 代码太重而无法呈现一样,并且在尝试向下滚动 html 表或在输入框中输入一些值时我得到“滞后”里面表(稍后通过单击按钮对其进行更新)。这是我的问题:我很确定我做错了什么会加载太多内存,因为我也在非常强大的计算机上进行了测试。即使完全禁用我的 CSS 也不行。

感谢您能给我的任何帮助,我们将不胜感激。

【问题讨论】:

  • 好吧,是的,如果你做 4000 个 jQuery 实例,4000 html() 和 4000 .prenpendTo 会很慢......
  • 所以我猜这是正常的?有没有办法可以加快整个过程?我需要我的应用程序快速且直观。
  • 让我做一些事情,我不能保证它会起作用......

标签: javascript jquery html css codeigniter


【解决方案1】:

问题

您在循环中使用了很多函数调用。这需要大量的果汁,而且你拥有的物品越多,速度就越慢。

为了解决这个问题,我们需要减少函数调用的次数。

我的建议

使用原生 JavaScript 可以节省性能。所以我建议你使用字符串连接而不是 jQuery 的 DOM 操作方法。

让你循环返工。由于您希望数据按后代顺序排列,因此我们需要反转循环:

for(i = data.length; i >= 0; i--)

然后简单的字符串连接构建一个tr。为此,您需要循环外的 var:

var myHTML = ''; //That's the one!
var i;
var item_cost = new Array();
var item_name = new Array();
var item_code = new Array();
var item_interno = new Array();

然后使用+= 构建tr。虽然,使用单行会使其更快,但可读性较差:

for(i = data.length; i >= 0; i--) {
    item_cost[i] = data[i].cost;
    item_name[i] = data[i].name;
    item_code[i] = data[i].code;
    item_interno[i] = data[i].codiceinterno;


    myHTML += '<tr>';
    myHTML += '<td>'+yourData+'</td>';//add those data here
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '</tr>';
}

然后,将其添加到您的表格中:

var myHTML = '';
var i;
var item_cost = new Array();
var item_name = new Array();
var item_code = new Array();
var item_interno = new Array();

for(i = data.length; i >= 0; i--) {
    item_cost[i] = data[i].cost;
    item_name[i] = data[i].name;
    item_code[i] = data[i].code;
    item_interno[i] = data[i].codiceinterno;


    myHTML += '<tr>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '<td>'+yourData+'</td>';
    myHTML += '</tr>';
}

$('#myTable').prepend(myHTML);

限制

根据我的测试,字符串长度可以是2^28,但不能是2^29。这使得最大长度约为。 268,435,456(大约可能不是最好的词,因为它介于 268,435,456536,870,912 之间。

如果您的数据字符数高于此值(但老实说,这将是 很多 数据),您可能需要将字符串拆分为 2 个变量。

【讨论】:

  • 当我回到办公室时,我肯定会试一试,同时我赞成这个答案。现在谢谢!
  • 是的,使用纯javascript总是更快
【解决方案2】:

我知道这不是你问题的真正答案,但是......

jQuery 肯定会导致滞后 - 难怪。但是 - 无论您选择 jQuery 来构建表格还是只是连接 HTML - 让我们同意这一点:4000 行绝对是很多数据。数据太多?我会说:200 已经是。如果我们数以千计,就会出现问题:为什么?是否有任何与应用程序相关的原因您真的需要一次检索如此大量的记录?其中一些可能永远不会被阅读。

为什么不尝试基于 ajax 的延迟加载方法?每次加载 50 条记录的部分似乎更健壮 IMO,并且肯定会是更好的 UX。

【讨论】:

  • 我为我的客户专门开发的应用程序需要这样做。你能给我一个你所说的“懒惰负载”的例子吗?你的意思是把结果分成几页?有没有简单的方法来实现这一目标?谢谢
  • 我没有任何示例,但我通常指的是一种机制(用于 FB 或重型画廊),其中 javascript 监视用户将页面滚动到给定阈值。当超过阈值时,ajax 会加载下一部分数据(在您的情况下:表行)。实际上,您可以设置您的代码,以便始终准备好下一个屏幕数据。延迟加载是一个流行的术语。
  • 我会检查它,但我认为当客户检查所有行并读取第 4000+ 行时,他无论如何都会滞后,不是吗?
  • 您可以提前预加载 100 行,以便在客户端开始滚动时方便使用数据开销。然后用户不应该感觉到滞后。这种无限滚动的缺点是在加载之前很难跳转到给定的数据部分。正如我所说,这完全取决于 UI 要求,但 4000 行似乎太多了,无法一次消化。
【解决方案3】:

我的两分钱:为什么不检索从服务器组成的行,而不是让客户端工作来复合它?你甚至可以缓存它。唯一的问题是你会有更多的流量,但在浏览器中它会更流畅

更新

要实现它,您可以使您的方法区分ajax是否输入,并仅显示$tbody,或根据它显示整个表格。它会是这样的:

$tbody = $this->load->view( 'view_with_oly_tbody', $data, true );
if ( $this->input->is_ajax_request() ) {
    return $tbody;
} else {
    $data['tbody'] = $tbody;
    $this->load->view('your_view_with_table_with_tbody_as_var', $data);
}

注意:上面的代码会根据您的视图、控制器、AJAX 中是否有 json、在其他部分写入返回等而有所不同。上面的代码只是为了澄清我对 CI 的观点。

啊!并且您必须在客户端管理答案以附加/前置/替换表的主体。

【讨论】:

  • 您有什么建议可以实现您所说的吗?感谢您的回答!
猜你喜欢
  • 2012-01-21
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
相关资源
最近更新 更多