[英]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"> </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";
};
我是角度和性能選擇的新手。 所以任何有關如何改進或不良練習突出顯示的提示都會非常有用!
長桌是角度最大的邪惡,因為像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.