如何优化向网页动态添加众多元素

时间:2019-06-03 18:28:42

标签: jquery html sql sql-server ajax

我需要从数据库中检索许多记录并将其显示给用户。我使用ajax进行此操作,并将应添加到页面的所有内容存储在单个字符串中。目前,我在加载时间上有问题(每100条记录1秒)。例如,加载1000行需要10秒,而查询本身可以在不到1秒的时间内完全执行。这意味着瓶颈正在创建元素并将其添加到网页中。

//client side code    
$(document).ready(function () {
    loadGrid(function () {
    $(".rowCount").val($(".tbody .tr:visible").length);
});

function loadGrid(callback) {
    $.ajax({
        type: "POST", url: "Ledger.aspx/LoadGrid",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            $(".tbody").html(response.d);   //response.d = '<div class='tr'> <div class='td colIdVchItm'>1</div>...</div>'
            callback();
        },
        failure: function (response) {
            ShowMessage(response.d);
        }
    });
}

//server side code
[WebMethod]
    public static string LoadGrid()
    {
        string q = @"select cast((select 'tr' as [@class],  
'td colIdVchItm' as [div/@class] , a.IdVchItm as [div], ' ',
'td colNo' as [div/@class] , a.No as [div], ' ',
'td colRef' as [div/@class] ,a.Ref as [div], ' ',
'td colSeq' as [div/@class] ,a.Seq as [div], ' ',
'td colDescr' as [div/@class] ,a.Descr as [div], ' ',
'td colDebit' as [div/@class] , cast(a.Debit as decimal(38,0)) as [div], ' ',
'td colCredit' as [div/@class] , cast(a.Credit as decimal(38,0)) as [div], ' ',
'td colBalance' as [div/@class] ,null as [div] , ' ',
'td colCur' as [div/@class] ,b.Title as [div], ' ',
'td colCurVal' as [div/@class] ,a.CurVal as [div], ' ',
'td colEffDate' as [div/@class] ,dbo.ShamsiDate(a.EffectiveDate) as [div] , ' '
from a inner join Currency as b on a.IdCur = b.IdCur order by a.vchdate, a.no
for xml path('div')) as nvarchar(max))";
        // this query returns every records as an html text. for example: 
        // <div class='tr'> <div class='td colIdVchItm'>1</div>...
        string res = "";
        SqlConnection con = new SqlConnection(DAL.conStr);
        SqlCommand com = new SqlCommand(q, con);
        con.Open();
        SqlDataReader rd = com.ExecuteReader();
        rd.Read();
        res = rd[0].ToString();
        con.Close();
        return res;
    }

如果能帮助我优化此过程,将不胜感激。

4 个答案:

答案 0 :(得分:2)

@Bhenam::$(“。tbody”)。html()内部使用innerHTML,这需要重建DOM,但具有append()jquery方法,该方法将内容添加到该节点中的子节点。

您可以尝试以下代码吗?

 success: function (response) {
            $(".tbody").html('');
             $(".tbody").append(response.d);

            callback();
        }

所有浏览器都支持。 https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild

答案 1 :(得分:0)

您的大多数代码看起来都不错,应该不会花费您提到的时间来尝试查看日志,看看从服务器端到客户端加载是否花费时间。

处理大量数据时,最重要的事情之一就是您应始终使用分页(负载x每页数据数量)。即使您的查询需要1-2秒执行,大量数据到达UI的时间也会基于客户端的网络连接而增加。

另一件事是,如果您只是从后端发送数据并在前端构建html字符串,则该数据将节省很多加载时间,因为它要少得多。

其他解决前端问题的快速提示是:

  • 尽可能限制访问DOM。您要访问DOM两次,一次是将html添加到tbody,第二次是在计算可见行的长度时,这可以通过仅从后端发送数据并计算长度并在前端创建html字符串来防止。您可以将其传递给负载网格回调函数。
  • 尝试使用ID(如果可能)。当使用类作为选择器时,它必须遍历整个DOM并检查该特定情况的多个情况。而且很可能是将行添加到单个位置。使用ID,这样就不必遍历文档的其余部分。
  • 尝试返回false;每个功能之后。在很多地方都没关系,但是如果您有一个巨大的javascript文件,这会稍微提高性能。

function() { //DOM manipulation code here ..... return false;

javascript的行为方式是,如果它看不到任何函数返回值,它将转到页面顶部并重新计算下一个要执行的函数或语句。如果您已退货,它将自动转到下一步。

我希望这会有所帮助。如果没有提供更多详细信息,并在可能的情况下显示性能和网络日志的屏幕截图。

答案 2 :(得分:0)

您将在单个请求中获取所有记录数据。您可以尝试延迟加载,而不是急于加载。

一次通过ajax获得200条记录。请在服务器端应用限制。

    var offset = 200,page=0; 
   //client side code    
    $(document).ready(function () {
        loadGrid(function () {
        $(".rowCount").val($(".tbody .tr:visible").length);
    });

    function loadGrid(callback) {
        $.ajax({
            type: "POST", url: "Ledger.aspx/LoadGrid",
            data: {offset:offset,start:page},
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (response) {
               if(response){

                $(".tbody").append(response.d);   //response.d = '<div class='tr'> <div class='td colIdVchItm'>1</div>...</div>'
                callback();
                 if($(".tbody .tr:visible").length % offset == 0){
                     page++;
                     loadGrid(callback);
                 } 
                }
            },
            failure: function (response) {
                ShowMessage(response.d);
            }
        });
    }

答案 3 :(得分:0)

尝试一下,如Madhusudana所述,请使用append()函数代替html(),如果您实际上使用html(),则ajax调用会为每个调用重绘整个页面:

//client side code    
    $(document).ready(function () {
        loadGrid(function () {
        $(".rowCount").val($(".tbody .tr:visible").length);
    });

function loadGrid(callback) {
    $.ajax({
        type: "POST", url: "Ledger.aspx/LoadGrid",
        data: "{}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            $(".tbody").append(response.d);   //response.d = '<div class='tr'> <div class='td colIdVchItm'>1</div>...</div>'
            callback();
        },
        failure: function (response) {
            ShowMessage(response.d);
        }
    });
}