Why our Angular app is always slow

http://www.zhex.me/blog/2013/11/22/why-out-angular-app-is-slow/

AngularJS as Google's open source JS front-end framework has been very popular recently. Add a few tags to html, write a few javascript codes according to the format, and a single-page application will always run. Its convenient experience, two-way data binding and other features give many front-end developers a good sense of intimacy. However, as everyone gradually started to use angular to develop a slightly larger project, it was found that the application was always very slow, which completely subverted the beautiful picture that angular gave us when it came up. Since we have to solve the problem, let's take a look at why our angular application is so slow.

Dirty checking

In order to achieve real-time synchronization of page data, Angular uses dirty checking to traverse the bound objects and compare the current and past values ​​of value. If the value changes, the change event is fired. Digest is the mechanism for performing dirty checking, triggered by $digest(). $digest() is executed every 50ms, triggering the dirty checking of the scope and its sub-scopes, and the dirty checking will trigger $watch() again, making the bound objects in the whole angular live.

It is because of such frequent triggering that dirty checking may become the source of performance problems. The official data is that angular will have performance problems when there are more than 2000 data bindings. This number is definitely enough in most cases. However, in some special cases, such as grid table, dropdown list with large data volume, Or in large data volume lists, 2000 data bindings will be consumed quickly.

$scope timer recycling

When many newbies start to contact angular, they do not have a good understanding of its operating mechanism, so they often add timers to the code to achieve some business requirements, and many people do not have the habit of recycling timers. In traditional web development, this is often not a problem, because once the page switches, the objects on the entire page disappear. In angular, all elements live on a single page. When the life cycle of the scope ends, there is no way to automatically clear these custom timers. Over time, a large number of expired timers survive on the page, and the memory is occupied. more and more powerful.

Things to avoid in development

Now that we understand the reasons for angular's slowness, we need to make some adjustments during the development process to avoid some problems that cause slowness.

1. Don't use data binding to render lists

Since data binding is the source of performance problems, we should avoid using it in certain situations, such as large data lists and grid tables. In particular, don't use it in those cases where it's just for presentation and doesn't need to dynamically update the data. Without angular, we can still use a template engine like handlebars and jquery to achieve it.

2. Don't execute data inline

ng-repeat will execute the method in the template every time $digest is executed, so in order to improve efficiency, do not use function filter expressions directly in the template, which will slow down the entire application.

1
2
<li ng-repeat="item in filteredItems()"> // 错误的方法,函数会被频繁调用
<li ng-repeat="item in items"> // 建议使用方法

3. Use data caching

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/* Controller */
// 基础数据 
var items = [{name:"John", active:true }, {name:"Adam"}, {name:"Chris"}, {name:"Heather"}];
// 初始化数据
$scope.displayedItems = items;
// 过滤缓存
var filteredLists['active'] = $filter('filter)(items, {"active" : true});
// 实现过滤器
$scope.applyFilter = function(type) {
    if (filteredLists.hasOwnProperty(type){ // Check if filter is cached
        $scope.displayedItems = filteredLists[type];
    } else {
        /* Non cached filtering */
    }
}
// Reset filter
$scope.resetFilter = function() {
    $scope.displayedItems = items;
}
1
2
3
/* View */
<button ng-click="applyFilter('active')">Select active</button>
<ul><li ng-repeat="item in displayedItems"><li></ul>

4. Use ng-if instead of ng-show when using additional templates

When displaying additional information through templates or directives, such as: Clicking an item to display item details, ng-if should be used instead of ng-show. This reduces the number of bound objects within the page.

1
2
3
4
5
6
7
<li ng-repeat="item in items">
    <p>  </p>
    <button ng-click="item.showDetails = !item.showDetails">Show details</buttons>
    <div ng-if="item.showDetails">
    </div>
</li>

5. Don't use ng-mouseenter and ng-mouseleave

Using angular's built-in ng-mouseenter, ng-mouseleave will cause the view to flicker. If you want to achieve some dynamic effects, it is recommended to use jQuery's animation.

6. Use ng-show to hide unwanted elements

The filter in ng-repeat creates a subset of metadata for each filter. When filtering, angular removes redundant elements from the $scope by calling the $destroy method. When the filter changes, re-associate the element back to the $scope. There is a performance overhead for each action. In most cases, this is fine, but if the operation is frequent, or the data table is very large, it will make Reduced performance. At this time, we can use computed properties to trigger ng-show and ng-hide, which can significantly improve performance.

1
2
<input ng-model="query"></input>
<li ng-repeat="item in items" ng-show="([item.name] | filter:query).length"></li>

7. Use debounce to filter data

1
2
3
4
5
6
7
8
/* Controller */
$scope.$watch('queryInput', function(newValue, oldValue) {
    if (newValue === oldValue) { return; }
    $debounce(applyQuery, 350);
});
var applyQuery = function() {
    $scope.filter.query = $scope.query;
};
1
2
3
/* View */
<input ng-model="queryInput"/>
<li ng-repeat=item in items | filter:filter.query> </li>

8. Destroy the timer

The timer cannot be automatically recycled, so we need to manually recycle it ourselves

1
2
3
4
5
6
7
8
9
var timer;
timer = $timeout(function () {
    // do something;
}, 1000);
$scope.$on('$destroy', function () {
    $timeout.cancel(timer);
});

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326993266&siteId=291194637
Recommended