我尝试在渲染具有多行(最小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"> </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> </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";
};
我是角度和性能选择的新手。所以任何有关如何改进或不良练习突出显示的提示都会非常有用!
答案 0 :(得分:3)
长桌是有角度的最大的邪恶,因为像ng-repeat一样慢的基础指令
一些简单而明显的内容:
我在行/单元格模板中看到很多绑定而没有一次性绑定(::)。我不认为你的行数据是变异的。切换到一次性绑定将减少观察者数量 - &gt;逆足
更难的东西:
快速回答:
不要让角度处理性能瓶颈
答案很长:
ng-repeat应该一次编译它的被抄送内容。但是使用ng-include会消除这个效果,导致每一行都在其包含ng的内容上调用编译。在大表中获得良好性能的关键是能够生成(是,手动,$ compile,$ interpolate和stuff)一个独特的编译行链接函数,尽可能少的角度指令 - 理想情况下只有一次表达式绑定,并手动处理行成瘾/删除(没有ng-repeat,你自己的指令,你自己的逻辑)
你应该至少找到一种避免第二次嵌套ng-repeat的方法。 ng-repeat =&#34; attobj in columns track by $ index&#34;&#39;。这是每行重复一次,导致编译和链接(渲染性能)和观察者数量(生命周期性能)
编辑:按照要求,一个天真的&#34;尽可能手动(和快速)处理表呈现的示例。请注意,该示例不处理生成表头,但它通常不是最困难的事情。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);
});
}
};
这是我用于自己项目的表格框架的方法(更好,更高级,但这确实是全球性的想法),允许使用角度功率来渲染单元格内容( &#39; getCellTemplate&#39;实现可以返回带有指令的html,它将被编译),使用过滤器甚至包括单元格中的指令,但保持表格渲染逻辑给自己,以避免无用的重复观看,并最小化编译过热到它的最低限度。