最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular ng-class performance issue when too many elements in DOM - Stack Overflow

programmeradmin2浏览0评论

I have been working on a plex angular page which has been causing performance issue. To highlight the problem I have created a fiddle / here.

Essentially the performance issue is being caused by ng-class statement which has a function in it.

<span class="done-{{todo.done}}" ng-class="myfunction()">{{todo.text}}</span>

The span is in an ng-repeat. On running the fiddle one can see that ng-class gets executed several times when the page loads and on each key up it gets called as many time as number of items in the TODO list.

This is a lot simpler case, in my case I have 780 items on my page and the function ends up being evaluated aroung 3000 times!

One of the solution we saw is to break up the scope but it will cause almost a rewrite of my app.

We also tried but it doesn't seem to be working with highly dynamic content.

Any thoughts?

I have been working on a plex angular page which has been causing performance issue. To highlight the problem I have created a fiddle http://jsfiddle/4ex2xgL1/3/ here.

Essentially the performance issue is being caused by ng-class statement which has a function in it.

<span class="done-{{todo.done}}" ng-class="myfunction()">{{todo.text}}</span>

The span is in an ng-repeat. On running the fiddle one can see that ng-class gets executed several times when the page loads and on each key up it gets called as many time as number of items in the TODO list.

This is a lot simpler case, in my case I have 780 items on my page and the function ends up being evaluated aroung 3000 times!

One of the solution we saw is to break up the scope but it will cause almost a rewrite of my app.

We also tried https://github./Pasvaz/bindonce but it doesn't seem to be working with highly dynamic content.

Any thoughts?

Share Improve this question asked Aug 25, 2014 at 7:31 MaheshMahesh 1,0811 gold badge12 silver badges29 bronze badges 4
  • In the real app, is the input to myfunction() dependent on the current item in ng-repeat? What sort of input does it need to produce a result? Possible solutions will depend on how dynamic the results from that function is. – ivarni Commented Aug 25, 2014 at 7:34
  • I would think to do not show 780 items. Show only visible items. Search in Google infinite list – Maxim Shoustin Commented Aug 25, 2014 at 7:35
  • 1 The other thing es up in my mind to do not use ng-class at all. Create directive instead that will change class regards to your needs (based on user behaviour) – Maxim Shoustin Commented Aug 25, 2014 at 7:37
  • @ivarni: we have nested ng-repeat and we have two condtions in ng-class .. if condtion true then myfunction() will be called . in condition we are using parent's ng-repeat and in myfunction() we used ng-repeat child ng-repeat – Mahesh Commented Aug 25, 2014 at 8:12
Add a ment  | 

2 Answers 2

Reset to default 2

I built a tree with https://github./JimLiu/angular-ui-tree with almost 500 items to render, with quite a lot of listeners. It takes 5 seconds to render. Bindonce won't work there.

The only solution out there is make ng-repeat do less. Keep the list small with a pagination, search or anything. Its the best shot as far as I know.

Well here are my remendations

  1. use ng-change on the checkbox to manipulate dom or anything rather using ng-class, it will improve your performance drastically.

    <li ng-repeat="todo in todos track by todo.id"> <input type="checkbox" ng-model="todo.done" ng-change="myfunction()"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li>

    http://jsfiddle/4ex2xgL1/3/

  2. use track by in ng-repeat if you have ids, more here http://www.codelord/2014/04/15/improving-ng-repeat-performance-with-track-by/

  3. dont show 780 items in a list. Use a searchbox to show some 100 or 50 or you know better

  4. quick-ng-repeat not used yet, try testing it https://github./allaud/quick-ng-repeat

finally a few good http://tech.small-improvements./2013/09/10/angularjs-performance-with-large-lists/

Finally I found the solution and it will helps lot to improve performance in angular js.

If your model changes dynamically and if you have lots of data and then also it improve AngularJS pages rendering up to 1000% and more - no kidding !.

Fore more information you can visit : http://orangevolt.blogspot.in/2013/08/superspeed-your-angularjs-apps.html

Follow the steps:

  1. download the library from the link:library

2.example without library:(check your console)

function MyController( $scope) {
    var entries = [ 
        { label : 'one', value : 'first entry'}, 
        { label : 'two', value : 'second entry'}, 
        { label : 'three', value : 'third entry'}
    ];
    
    $scope.label ="";
    $scope.value ="";
    $scope.order = 'label';
    
    $scope.add = function() {
        entries.push({ 
            label : $scope.label, 
            value : $scope.value
        });
    };
        
    $scope.getEntries = function() {
        console && console.log( "getEntries() called");
        return entries;
    };
}
<script src="https://raw.githubusercontent./lodash/lodash/2.4.1/dist/lodash.js"></script>
<script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis./ajax/libs/jquery/1.10.0/jquery.min.js"></script>

<form name="myform" ng-app ng-controller="MyController">
    Label/Value :
    <input type="text" required ng-model="label">
    <input type="text" required ng-model="value">
    <button 
        ng-disabled="!myform.$valid" 
        ng-click="add()"
    >Add</button>
        
    <fieldset>    
        <legend>
            Entries sorted by 
            <select 
                ng-model="order" 
                ng-options="property for property in [ 'label', 'value']">
            </select>
        </legend>
        <div ng-repeat="entry in getEntries() | orderBy:order">
            {{entry.label}} = "{{entry.value}}"
        </div>
    </fieldset>
</form>

3.example with library:(check your console)

function MyController( $scope) {
    var entries = [ 
        { label : 'one', value : 'first entry'}, 
        { label : 'two', value : 'second entry'}, 
        { label : 'three', value : 'third entry'}
    ];
    
    $scope.label ="";
    $scope.value ="";
    $scope.order = 'label';
    
    $scope.add = function() {
        entries.push({ 
            label : $scope.label, 
            value : $scope.value
        });
            // clear cache
        $scope.getEntries.cache = {};
    };
        
    $scope.getEntries = _.memoize( 
        function() {
            console && console.log( "getEntries() sorted by '" + $scope.order + " 'called");
                // return entries sorted by value of $scope.order
            return _.sortBy( entries, $scope.order);
        }, 
        function() { 
                // return the cache key for the current result to store 
            return $scope.order;
        }
    );
}
<script src="https://raw.githubusercontent./lodash/lodash/2.4.1/dist/lodash.js"></script>
<script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<script src="https://ajax.googleapis./ajax/libs/jquery/1.10.0/jquery.min.js"></script>

<form name="myform" ng-app ng-controller="MyController">
    Label/Value :
    <input type="text" required ng-model="label">
    <input type="text" required ng-model="value">
    <button 
        ng-disabled="!myform.$valid" 
        ng-click="add()"
    >Add</button>
        
    <fieldset>    
        <legend>
            Entries sorted by 
            <select 
                ng-model="order" 
                ng-options="property for property in [ 'label', 'value']">
            </select>
        </legend>
        <div ng-repeat="entry in getEntries()">
            {{entry.label}} = "{{entry.value}}"
        </div>
    </fieldset>
</form>

发布评论

评论列表(0)

  1. 暂无评论