`
shappy1978
  • 浏览: 702949 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

为什么我们的 Angular 应用总是很慢

    博客分类:
  • Web
 
阅读更多

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

AngularJS 作为 Google 开源的 JS 前端框架最近一直很火。 在 html 中加上几个标签, 根据格式写几句 javascript 代码, 一个单页应用就总跑起来了。其方便的上手体验, 双向数据绑定等特性给了很多前端开发者很好的亲切感。 而然随着大家逐渐用 angular 开始开发稍大一点的项目,发现做出来的应用总是非常慢,这完全颠覆了 angular 上来时给我们描绘的美好画面。既然遇到问题就要解决,让我们来看看为什么我们的 angular 应用这么慢。

Dirty checking

为了实现页面数据的实时同步,angular 采用 dirty checking 来遍历绑定的对象,比较 value 现在和过去的值。如果 value 有发生变化,就触发 change 事件。 Digest 是执行 dirty checking 的机制, 由 $digest() 触发。 $digest() 每50ms执行一次,触发所属 scope 和其子 scope 的 dirty checking, dirty checking 又会触发 $watch(), 使整个 angular 中绑定的对象活起来。

正是因为这样频繁的触发,使得 dirty checking 有可能成为性能问题的根源。 官方给出的数据是 angular 在2000个数据绑定以上才会出现性能问题, 这个数字在大多数情况下肯定是够用了,然而在一些特殊情况,比如 grid table, 大数据量的 dropdown list,或者大数据量的列表中, 2000个数据绑定很快就会被消耗完了。

$scope 定时器回收

当很多新手开始接触 angular 的时候并没有很好的了解其运行机制,所以经常会为了达到一些业务需求上的目的而在代码中添加定时器,并且很多人都没有对定时器作回收的习惯。在传统的 web 开发中,这常常不是问题,因为一旦页面切换,整个页面上的对象也都消失了。 而在 angular 中,所有元素都存活在单页面上,当 scope 的生命周期结束时没有办法自动清楚这些自定义的定时器,久而久之, 页面中存活着大量已经过期的定时器,内存被占用也越来越厉害。

开发中需要避免的事

既然已经明白了 angular 慢的原因,我们就需要在开发过程中做一些调整,避免一些导致慢的问题出现。

1. 不要用数据绑定来渲染列表

既然数据绑定时性能问题的根源, 我们就应该避免在特定的情况下使用,大数据列表和 grid table 就是。特别时在那些只是为了作展示,而不需要对数据做动态更新的情况下,就别用了。没有了angular, 我们还是可以用 handlebars 之类的模版引擎加上 jquery 来实现。

2. 不要用内联方式实行数据

ng-repeat 会在每次执行 $digest 的时候执行模版内的方法,所以为了提高效率,不要直接在模版内使用函数过滤表达式,这样会拖慢整个应用。

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

3. 使用数据缓存

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. 在使用额外的模版时,用 ng-if 代替 ng-show

当通过模版或者 directive 来显示附加信息时,比如: 点击商品显示商品详细信息时, 应该使用 ng-if 代替 ng-show。 这可以减少页面内绑定对象的数量。

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. 不要使用 ng-mouseenter 和 ng-mouseleave

使用 angular 内建的 ng-mouseenter, ng-mouseleave 会导致视图闪烁。 如果想实现一些动态效果,建议使用 jQuery 的 animation。

6. 使用 ng-show 来隐藏不需要的元素

在 ng-repeat 中的 filter 会为每个过滤创建一个元数据的子集。 过滤时,angular 通过调用 $destroy 方法把多余的元素从 $scope 中移除。 当过滤器发生变化的时候又把元素重新关联回 $scope. 每一次动作都会产生性能开销,多数情况下,这样做是没有问题的, 但如果操作频繁,或者数据表非常大的话,就会使性能降低。 这个时候我们可以用计算属性的方法来触发 ng-show 和 ng-hide, 这样可以明显提高性能。

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

7. 使用 debounce 过滤数据

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. 销毁定时器

定时器无法被自动回收,所以我们需要自己手动回收

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

相关推荐

    适用于Angular和渐进式Web应用PWA的高效异步本地存储模块

    6. **集成与扩展**:对于Angular应用,这个模块很可能已经考虑了与Angular的依赖注入系统集成,使得服务可以在任何需要的地方被注入和使用。同时,它可能还提供了扩展点,允许开发者根据需求自定义存储策略或者增加...

    angular-strap 完没解决bootstrap组件与angularjs交互问题

    `angular-strap`是一个致力于解决这个问题的库,它为AngularJS提供了Bootstrap组件的指令和服务,使得在AngularJS应用中使用Bootstrap变得更加方便。然而,尽管`angular-strap`在很多情况下能够很好地融合这两者,但...

    angular.js资料

    通过掌握Angular.js,开发者能够开发出更加动态、响应快速且易于维护的现代Web应用,这些应用不仅适用于传统的桌面浏览器,也能够很好地适配各种移动设备。随着技术的不断更新,Angular.js也在不断地进行版本迭代,...

    详解用webpack2搭建angular2的项目

    我们将从零开始,逐步构建一个完整的 Angular 2 项目,并学习如何使用 Webpack 2 来管理和优化我们的项目。 Webpack 2 简介 Webpack 2 是一个流行的 JavaScript 模块打包工具,用于将多个 JavaScript 文件合并成一...

    详解Angular 开发环境搭建

    4. **安装Angular CLI**: Angular CLI(命令行界面)是开发Angular应用的强大工具,它可以自动化很多开发过程,如生成新组件、服务、模块等。在全局安装CLI: ``` npm i @angular/cli -g ``` 5. **创建Angular...

    angularjs+require+angular-ui-router

    在本文中,我们将深入探讨如何使用AngularJS、RequireJS和Angular-UI-Router构建一个高效且模块化的前端应用。AngularJS是一种流行的JavaScript框架,用于构建动态网页应用;RequireJS是AMD(Asynchronous Module ...

    Angular Profiler-crx插件

    Angular Profiler是一款专为Angular开发者设计的Chrome浏览器扩展程序,它提供了强大的性能分析和调试工具,旨在优化Angular应用的开发流程。这款插件对于那些希望提升Angular应用程序性能、查找性能瓶颈以及优化...

    sms-backup-reader-2:新铸造的Angular版本的SMS Backup Reader

    短信备份阅读器2 这是一个基于Angular的Web应用程序,旨在读取由Ritesh的Android应用程序SMS备份和还原生成的XML备份...加载特定的对话可能会很慢,并且会冻结UI 加载数据后使用设置时应用程序中断 如果您遇到其他问

    grails3-angular2:Grails 3 Angular 2

    请记住以下几点: TypeScript编译有效,但仍然很慢(我将努力对其进行改进)。 Angular2目前处于Alpha中,并且是一个移动的目标,因此事情可能无法按预期进行。应用程序这是一个用Angular2编写的简单的hello world...

    angular-abortable-requests:AngularJS 应用程序中可中止的 AJAX 请求

    ####为什么? 大型 Web 应用程序需要大量信息才能运行。 无论是在菜单和选项卡之间导航还是只是单击,应用程序都必须发出大量 Ajax 请求才能从服务器获取数据。 很多时候,应用程序最终不需要所有的请求,因为...

    impresser-html-angular-minifier

    "impresser-html-angular-minifier" 是一个专为AngularJS应用程序设计的HTML缩小工具。它主要针对JavaScript环境,特别是对于那些使用AngularJS框架构建的Web应用。在开发阶段,为了提高代码可读性和调试便捷性,...

    angular-netstatus:检测和操纵AngularJS应用程序中的在线状态

    手动强制脱机模式在浏览器处于联机状态的情况下很有用,但是连接速度太慢或不可靠,导致应用程序无响应。安装使用安装: $ bower install angular-netstatus将src/netstatus.js添加到您的项目中。 许多构建工具会...

    social-network-mean-stack:使用MEAN Stack(Node.js,Angular 4,Express.js和MongoDB)的聊天Web应用程序

    演示链接: : (免费托管和免费数据库都很慢。因此,请耐心等待,因为那里没有正在加载的UX。也许我会尽快添加它) 在本地尝试 确保MongoDB在计算机上的端口27017上运行,并且3000端口可用于运行node.js服务器 &gt; ...

    详解angularjs4部署文件过大解决过程

    在AngularJS4的应用开发中,我们可能会遇到一个问题:部署的文件大小过于庞大,导致加载速度慢,用户体验下降。本文将详细解析这个问题的原因并提供解决方案。 首先,当我们在开发环境中使用`ng build`命令进行打包...

    ng-js:Angular JS 微版(学习用)

    它不是用于生产的,它没有很好地测试,并且没有努力优化性能,所以它很慢。实施了什么只实现了真正的基本功能。 它们以简化的形式实现。 API 也可能不同。 列表: 预定义指令自定义指令的 API( priority 、 link ...

    web前端单页面应用

    **单页面应用(SPA)详解** 单页面应用(Single Page Application,简称SPA)是一种现代的Web应用程序设计模式,它在用户与网站交互时无需加载整个新页面,而是仅更新部分DOM(文档对象模型)来刷新视图。这种设计...

    基于BS体系结构开发应用系统设计方案

    【基于BS体系结构开发应用系统设计方案】 在信息技术领域,基于Browser/Server(BS)体系结构的开发模式已经成为构建网络应用系统的一种主流方式。BS体系结构,又称为浏览器/服务器架构,其核心特点是用户通过Web...

    任何可以渲染到DOM的东西都可以使用domtestinglibrary进行测试

    通过学习和应用这些示例,你可以掌握如何有效地测试你的JavaScript应用,无论它们是基于什么框架构建的。 总结起来,`dom-testing-library`是一个强大的工具,它提供了一种以用户为中心的测试方法,帮助开发者编写...

    SRReactNode:一个应用演示,展示使用 Node 和 React 实现服务器端渲染

    JavaScript 驱动的 MVC(angular、ember、backbone 等)在 DOM 负载上呈现,这可能真的很慢wwww 并且会导致糟糕的用户体验。 它们不能被搜索引擎索引(无需为等第三方服务支付 $$)。 如果您的应用程序提供人们可能...

    Vuejs开发环境搭建及热更新【推荐】

    相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用,特别适合单页应用的开发。 Vue.js是数据驱动的,它通过一些特殊的语法,将DOM和数据绑定起来,无需手动操作DOM。一旦创建...

Global site tag (gtag.js) - Google Analytics