簡體   English   中英

角度性能:關鍵渲染路徑?

[英]angular performance: critical rendering path?

我試圖在渲染具有許多行的表時(頁面最小25x)優化頁面加載速度。

我沒有經驗調試/提高角度應用程序的性能,因此在這種速度不足的情況下可能會失敗。

以下是針對5行查詢的Chrome時間線報告:

在此輸入圖像描述

以下是針對100行查詢的Chrome時間線報告:

在此輸入圖像描述

隨着在表上呈現更多行,XHR加載(api / list / json / Chemical ...)會隨着時間的推移而增加。

快速返回服務器對數據的響應(不是瓶頸):

這是表格的模板:

            <tbody ng-if="compressed">
              <tr ng-if="dbos && (rows.length == 0)">
                <td class="tableColumnsDocs"><div class="tableButtons">&nbsp;</div></td>
                <td class="tableColumnsDocs"><div>No results</div></td>
                <td class="tableColumnsDocs" ng-repeat="attobj in columns track by $index" ng-if="$index > 0">
                  <p>&nbsp;</p>
                </td>
              </tr>
              <tr class="tableRowsDocs" ng-repeat="dbo in rows track by $index">
                <td class="tableColumnsDocs"><div ng-include="'link_as_eye_template'"></div></td>
                <td class="tableColumnsDocs" ng-repeat="attobj in columns track by $index">
                  <div ng-init="values = dbo.get4(attobj.key); key = attobj.key; template = attobj.template || getAttributeTemplate(dbo.clazz + attobj.key);">

                    <div class="content" ng-include="template"></div>
                    <div class="contentFiller" ng-include="template"></div>
                  </div>
                </td>
              </tr>           
            </tbody>

這里的模板會調用:

<script type="text/ng-template" id="plain_values_template">
      <p ng-repeat="v in values track by $index">{{ v }}</p>
</script>

<script type="text/ng-template" id="links_as_dns_template">
      <div ng-repeat="dbo in values track by $index" ng-include="'link_as_dn_template'"></div>
</script>

<script type="text/ng-template" id="json_doc_template">
  <textarea class="form-control" rows="{{values.length + 2}}" ng-trim="false" ng-readonly="true">{{ values | json }}</textarea>
</script>

<script type="text/ng-template" id="link_as_dn_template">
  <a href="#/view/{{ dbo.cid }}"><p>{{ dbo.displayName() }}</p></a>

相關控制器部分:

      $scope.getAttributeTemplate = function(str) {
    //console.log("getAttributeTemplate"); console.log(str);
    if ($templateCache.get(str + ".template")) {
      return str + ".template";
    }
    var a = str.split(/(>|<)/);
    //console.log(a);
    if ((a.length - 1) % 4 == 0) {
      return "links_as_dns_template";
    }
    var clsname = a[a.length - 3];
    if (clsname == "*") {
      return "plain_values_template";
    }
    var attname = a[a.length - 1];
    var cls = datamodel.classes[clsname];
    var att = cls.attribute[attname];
    if (!att) {
      return "plain_values_template";
    }
    if (att.type == "ref") {
      return "links_as_dns_template";
    }
    return "plain_values_template";
  };

在此輸入圖像描述

我是角度和性能選擇的新手。 所以任何有關如何改進或不良練習突出顯示的提示都會非常有用!

長桌是角度最大的邪惡,因為像ng-repeat這樣的地獄般緩慢的基礎指令

一些簡單明了的東西:

我在行/單元格模板中看到很多綁定而沒有一次性綁定(::)。 我不認為你的行數據是變異的。 切換到一次性綁定將減少觀察者數量 - >性能。

一些更難的東西:

快速回答 :

不要讓角度處理性能瓶頸

答案很長:

ng-repeat應該編譯它的被轉換內容一次。 但是使用ng-include會消除這個效果,導致每一行都在其包含ng的內容上調用編譯。 在大表中獲得良好性能的關鍵是能夠生成(是,手動,$ compile,$ interpolate和stuff)一個獨特的編譯行鏈接​​函數,盡可能少的角度指令 - 理想情況下只有一次表達式綁定,並手動處理行成癮/刪除(沒有ng-repeat,你自己的指令,你自己的邏輯)

你應該至少找到一種方法來避免第二次嵌套的ng-repeat在'ng-repeat =“attobj in columns track by $ index”'。 這是每一行的雙重重復,導致編譯和鏈接(渲染性能)和觀察者數量(生命周期性能)

編輯:正如所問,一個“天真”的例子,說明如何盡可能手動(和快速)處理表格渲染。 請注意,該示例不處理生成表頭,但通常不是最困難的事情。

function myCustomRowCompiler(columns) {

    var getCellTemplate = function(attribute) {
        // this is tricky as i dont know what your "getAttributeTemplate" method does, but it should be able to return
        // the cell template AS HTML -> you maybe would need to load them before, as getting them from your server is async.

        // but for example, the naive example to display given attribute would be
        return $('<span>').text("{{::model."+ attribute +"}}"); // this is NOT interpolated yet
    };


    var myRowTemplate = $('<tr class="tableRowsDocs">');

    // we construct, column per column, the cells of the template row
    _.each(columns, function(colAttribute, cellIdx) {
        var cell = $("<td>");
        cell.html(getCellTemplate());
        cell.appendTo(myRowTemplate);
    })

    return $compile(myRowTemplate); // this returns the linking function
}

和天真的用法:

function renderTableRows(dbos, columns) {

    var $scope; // this would be the scope of your TABLE directive
    var tableElement = $el; // this would be your table CONTENT

    var rowLinker = myCustomRowCompiler(columns); // note : in real life, you would compile this ONCE, but every time you add rows.


    for(var i=0; i<dbos; i++) {
        var rowScope = $scope.$new(); // creating a scope for each row
        rowScope.model = dbos[0]; // injecting the data model to the row scope
        rowLinker(rowScope, function(rowClone) { // note : you HAVE to use the linking function second parameter, else it will not clone the element and always use the template
            rowClone.appendTo(tableElement);
        });
    }

};

這是我一直用於我自己項目的表框架的方法(嗯,更高級,但這確實是全局的想法),允許使用角度功率來呈現單元格內容('getCellTemplate'實現可以返回帶有指令的html ,將被編譯),使用過濾器甚至包括單元格中的指令,但保持表格渲染邏輯給自己,以避免無用的重復觀看,並最大限度地減少編譯過熱到最小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM