Javascript 提高ng repeat(只读html表)在Angular中的渲染性能
我已经阅读了六篇关于使用ng repeat提高性能的文章,到目前为止,我还没有找到一种直接的方法来改进简单的bind once表的呈现 我已经分析了各种方法,到目前为止,我能做的最好的方法是对大约4400行进行5秒的渲染 **关于这个测试用例的注释。我正在使用一个更大的数据集将性能测试推向一个具有挑战性的数据集。通常,表的行数为1000行或更少。我希望避免分页,因为在许多情况下,查看所有数据对于扫描异常非常有用。更重要的是,300行的渲染时间对我来说也是不可接受的,因为它会在短时间内冻结浏览器,而这正是我想要消除的。我充分意识到渲染更少的数据会更快,我正在考虑最大化更大数据集的性能 我最初的做法Javascript 提高ng repeat(只读html表)在Angular中的渲染性能,javascript,angularjs,performance,angularjs-directive,Javascript,Angularjs,Performance,Angularjs Directive,我已经阅读了六篇关于使用ng repeat提高性能的文章,到目前为止,我还没有找到一种直接的方法来改进简单的bind once表的呈现 我已经分析了各种方法,到目前为止,我能做的最好的方法是对大约4400行进行5秒的渲染 **关于这个测试用例的注释。我正在使用一个更大的数据集将性能测试推向一个具有挑战性的数据集。通常,表的行数为1000行或更少。我希望避免分页,因为在许多情况下,查看所有数据对于扫描异常非常有用。更重要的是,300行的渲染时间对我来说也是不可接受的,因为它会在短时间内冻结浏览器,
<tbody>
<tr ng-repeat="f in vm.rowDetails">
<td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td>
<td class="w100">{{f.Code}}</td>
<td class="w50">{{f.Class}}</td>
<td>{{f.WebName}}</td>
<td>{{f.Category}}</td>
<td>{{f.MktgCode}}</td>
</tr>
</tbody>
{{f.Code}}
{{f.Class}}
{{f.WebName}}
{{f.Category}}
{{f.MktgCode}
渲染约7秒
添加了绑定一次属性(从angular 1.3开始提供)(尽管它不适用于ng repeat指令
<tbody>
<tr ng-repeat="f in vm.rowDetails">
<td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td>
<td class="w100">{{::f.Code}}</td>
<td class="w50">{{::f.Class}}</td>
<td>{{::f.WebName}}</td>
<td>{{::f.Category}}</td>
<td>{{::f.MktgCode}}</td>
</tr>
</tbody>
<tbody pm-table-body items="vm.rowDetails">
{{::f.Code}
{{::f.Class}
{{::f.WebName}
{{::f.Category}
{{::f.MktgCode}
没有明显的改善。我想这是意料之中的,因为这优化了后续的观察周期
开始尝试我自己的行-字符串连接
<tbody>
<tr pm-table-row f="f" ng-repeat="f in vm.rowDetails track by $index"></tr>
</tbody>
指令:
angular.module('app').directive('pmTableRow', ['$interpolate', function ($interpolate) {
var template2 = '' +
'<td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td> ' +
'<td class="w100">Code</td>' +
'<td class="w50">Class</td>' +
'<td>WebName</td>' +
'<td>Category</td>' +
'<td>MktgCode</td>';
return {
restrict: 'A',
replace: false,
scope: { f: '=' },
link: function ($scope, $element, $attr) {
var fields = ['Code', 'Class', 'WebName', 'Category', 'MktgCode'];
var t = template2;
var f = $scope.f;
for (var k in fields)
t = t.replace(fields[k], f[fields[k]]);
$element.html(t);
}
}}]);
angular.module('app').directive('pmTableBody', ['$interpolate', function ($interpolate) {
var template2 = '' +
'<tr><td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td> ' +
'<td class="w100">Code</td>' +
'<td class="w50">Class</td>' +
'<td>WebName</td>' +
'<td>Category</td>' +
'<td>MktgCode</td></tr>';
return {
restrict: 'A',
replace: false,
scope: { items: '=' },
link: function ($scope, $element, $attr) {
var fields = ['Code', 'Class', 'WebName', 'Category', 'MktgCode'];
var lines = [];
$scope.$watch('items', function () {
var items = $scope.items;
var t1 = new Date();
var t = template2;
for (var i = 0; i < items.length; i++) {
var f = items[i];
for (var k in fields) {
t = t.replace(fields[k], f[fields[k]]);
lines.push(t);
}
}
console.log('pmTableBody html concatenation done in: ', (new Date() - t1)/1000); // done in 0.02 seconds
$element.html(lines.join(''));
});
}
}}]);
<tr ng-repeat="f in ::vm.rowDetails track by $index">
angular.module('app')。指令('pmTableRow',['$interpolate',函数($interpolate){
var template2=''+
' ' +
“代码”+
“阶级”+
“网络名称”+
“类别”+
“MktgCode”;
返回{
限制:“A”,
替换:false,
作用域:{f:'='},
链接:函数($scope、$element、$attr){
变量字段=['Code'、'Class'、'WebName'、'Category'、'MktgCode'];
var t=模板2;
var f=$scope.f;
for(字段中的变量k)
t=t.replace(字段[k],f[fields[k]]);
$element.html(t);
}
}}]);
这似乎是一个进步,但不是很大的进步。渲染时间下降到了~4.7秒
最后,我尝试完全删除ng repeat,并在指令中生成tBody字符串
<tbody>
<tr ng-repeat="f in vm.rowDetails">
<td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td>
<td class="w100">{{::f.Code}}</td>
<td class="w50">{{::f.Class}}</td>
<td>{{::f.WebName}}</td>
<td>{{::f.Category}}</td>
<td>{{::f.MktgCode}}</td>
</tr>
</tbody>
<tbody pm-table-body items="vm.rowDetails">
指令:
angular.module('app').directive('pmTableRow', ['$interpolate', function ($interpolate) {
var template2 = '' +
'<td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td> ' +
'<td class="w100">Code</td>' +
'<td class="w50">Class</td>' +
'<td>WebName</td>' +
'<td>Category</td>' +
'<td>MktgCode</td>';
return {
restrict: 'A',
replace: false,
scope: { f: '=' },
link: function ($scope, $element, $attr) {
var fields = ['Code', 'Class', 'WebName', 'Category', 'MktgCode'];
var t = template2;
var f = $scope.f;
for (var k in fields)
t = t.replace(fields[k], f[fields[k]]);
$element.html(t);
}
}}]);
angular.module('app').directive('pmTableBody', ['$interpolate', function ($interpolate) {
var template2 = '' +
'<tr><td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td> ' +
'<td class="w100">Code</td>' +
'<td class="w50">Class</td>' +
'<td>WebName</td>' +
'<td>Category</td>' +
'<td>MktgCode</td></tr>';
return {
restrict: 'A',
replace: false,
scope: { items: '=' },
link: function ($scope, $element, $attr) {
var fields = ['Code', 'Class', 'WebName', 'Category', 'MktgCode'];
var lines = [];
$scope.$watch('items', function () {
var items = $scope.items;
var t1 = new Date();
var t = template2;
for (var i = 0; i < items.length; i++) {
var f = items[i];
for (var k in fields) {
t = t.replace(fields[k], f[fields[k]]);
lines.push(t);
}
}
console.log('pmTableBody html concatenation done in: ', (new Date() - t1)/1000); // done in 0.02 seconds
$element.html(lines.join(''));
});
}
}}]);
<tr ng-repeat="f in ::vm.rowDetails track by $index">
angular.module('app')。指令('pmTableBody',['$interpolate',函数($interpolate){
var template2=''+
' ' +
“代码”+
“阶级”+
“网络名称”+
“类别”+
“MktgCode”;
返回{
限制:“A”,
替换:false,
作用域:{items:'='},
链接:函数($scope、$element、$attr){
变量字段=['Code'、'Class'、'WebName'、'Category'、'MktgCode'];
var行=[];
$scope.$watch('items',function(){
var items=$scope.items;
var t1=新日期();
var t=模板2;
对于(变量i=0;i
由于某些原因,这将渲染时间增加到28秒。因此,我可能忽略了一些明显的内容
我希望渲染时间小于1s
更新我在复制的对象上创建了一个唯一的id字段,从而删除了track by$index。到目前为止,性能没有明显变化,但我会继续尝试
更新
我添加了一个基于的手表计数器。以下是结果:
4400行和ng重复进近,有26102名观察者
使用tr pm表格行方法,有4457个观察者,最后使用pm表格体方法,有57个观察者!有趣的是,这是迄今为止执行最慢的方法
更新
有趣的是,在进一步分析之后,pm表体方法似乎使用了很多角度动画功能。
禁用动画后,(程序)需要10秒
因此,浏览器在很长一段时间内仍然没有响应,仍然在对那里发生的事情进行故障排除。如果要提高渲染性能,应该使用
limito
过滤器并在页面上实现分页,另一种方法是使用此ngInfiniteScroll在一个页面上查看整个表
如果您想了解此表中的某种搜索,请使用另一个筛选器ng repeat=“item in items | filter:searchString”将应用于整个数据集,不仅适用于您的有限视图,而且您需要记住,
filter
filter应该在limito
之前首先执行。请尝试将bind once属性放在ng repeat
指令中:
angular.module('app').directive('pmTableRow', ['$interpolate', function ($interpolate) {
var template2 = '' +
'<td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td> ' +
'<td class="w100">Code</td>' +
'<td class="w50">Class</td>' +
'<td>WebName</td>' +
'<td>Category</td>' +
'<td>MktgCode</td>';
return {
restrict: 'A',
replace: false,
scope: { f: '=' },
link: function ($scope, $element, $attr) {
var fields = ['Code', 'Class', 'WebName', 'Category', 'MktgCode'];
var t = template2;
var f = $scope.f;
for (var k in fields)
t = t.replace(fields[k], f[fields[k]]);
$element.html(t);
}
}}]);
angular.module('app').directive('pmTableBody', ['$interpolate', function ($interpolate) {
var template2 = '' +
'<tr><td class="checkbox-column"><input type="checkbox" ng-model="f.selected" /></td> ' +
'<td class="w100">Code</td>' +
'<td class="w50">Class</td>' +
'<td>WebName</td>' +
'<td>Category</td>' +
'<td>MktgCode</td></tr>';
return {
restrict: 'A',
replace: false,
scope: { items: '=' },
link: function ($scope, $element, $attr) {
var fields = ['Code', 'Class', 'WebName', 'Category', 'MktgCode'];
var lines = [];
$scope.$watch('items', function () {
var items = $scope.items;
var t1 = new Date();
var t = template2;
for (var i = 0; i < items.length; i++) {
var f = items[i];
for (var k in fields) {
t = t.replace(fields[k], f[fields[k]]);
lines.push(t);
}
}
console.log('pmTableBody html concatenation done in: ', (new Date() - t1)/1000); // done in 0.02 seconds
$element.html(lines.join(''));
});
}
}}]);
<tr ng-repeat="f in ::vm.rowDetails track by $index">
以下几点可能会有所帮助: 我知道你说你是
track by$index
,因为你在测试中复制了你的条目,但是如果f
有一个唯一的属性,比如ID,它会加快执行track by f.ID
如果您使用的是ngAnimate,禁用它可以加快渲染时间
仅使用视口中的渲染项执行某些操作,因此您仍然可以将它们全部显示在视口中