繁体   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