AngularJs项目实践总结

今年3月接触AngularJs,并且在6月的项目中开始应用,从踩坑到填坑花了不少时间,根据项目中的实际应用情况总结了一些经验,如下:

一.UI控件选择

Angularjs是不缺控件的,Github里现成的控件非常丰富,基本上足以应付一个普通管理系统中常见的控件需求。但是控件的丰富会带来选择的困难。选择控件要满足几个原则:
原则1:符合业务场景
原则2:控件持续更新
原则3:满足性能要求

举几个例子。首先是上传附件的控件。项目中要用到附件上传,谷歌上搜到了三个控件,分别是
https://github.com/leon/angular-upload
https://github.com/danialfarid/ng-file-upload
https://github.com/nervgh/angular-file-upload

因为项目需要兼容IE9,就重点关注了这三个控件对浏览器的兼容性。第一个控件没有任何说明,第二个控件支持IE9,但是前提是要安装flash,第三个控件支持IE8和9,但是只支持部分功能。从浏览器兼容性的角度考虑,最终选择了控件三。

再举一个例子,下拉框控件。html原生的select功能比较单一,并且option的样式很难修改,在前端各个框架所用的下拉框基本上都是重新实现的。Angularjs也不例外。项目中刚开始选用了ui-select2。后来在ui-select2的介绍中看到这句话:
This directive is now obsolete. A new initiative, more active, and 100% angular is available at https://github.com/angular-ui/ui-select.
发现ui-select2已经有3年没有更新了,果断弃坑选用ui-select。

最后谈谈原则3,还是说ui-select吧,它虽然是ui-select2的改进版,但是性能上是存在问题的,根据stackoverflow上的问答,一个ui-select里包含过多选择项或者一个页面包含过多ui-select控件时,性能有明显降低。因为这一点,曾考虑用其他控件替换掉ui-select,不过项目中并不存在大数据量和过多控件的情况,最后仍然保留了它。在满足原则1和2和前提下,只能尽量满足原则3。

一个新项目在开发前,最好能根据需求调研可能用到的UI控件,并尝试写一些demo,尤其对复杂的UI控件。比如ui-grid,有太多的指令和api,花费在阅读文档和官方实例代码的时间也是一笔不小的投入。

二.自定义指令

自定义的指令要加命名空间(前缀),防止全局指令名污染,就像javascript中防止全局变量污染一样。在项目中,某个页面出现了这样的错误:
Error: [$compile:multidir] Multiple directives [refresh, uiSelectChoices] asking for template on: <ui-select-choices repeat="searchRes in searchRes" refresh="searchMedia($select)">

但是新建一个测试用的解决方案,ui-select却是正常的。几经搜索,后来才发现在项目公共的directive里定义了一个叫refresh的指令,它和ui-select的refresh指令重名了。
解决办法很简单,重命名自定义的refresh指令。

三.页面防抖动

在页面初始化的时候,用户可能会先看到 {{ }},然后闪烁一下才出现真正的内容。这是因为Angularjs会在dom加载完后才会解析{{ }}中的内容,在这之前,{{ }}不是Angularjs的插值表达式,而是文本。
解决办法:
1. 在要显示的内容上使用 ng-cloak指令,并且添加如下样式

<style>
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak
{
display: none !important;
}
</style>

2. 使用 ng-bind 替代 {{ }}

四.模块化思维

Angularjs推荐模块化开发,module的本意即是模块化,但是在Angularjs 1.X中,module更多体现出来的是一个“命名空间”的概念,而不是真正意义上的模块化。比如A模块依赖B模块,B模块应该是一个独立的东西,但是被A引用之后,A、B模块中的指令,服务,控制器全部混在了一起,使用指令、控制器时甚至不需要指定是哪个模块中的指令和控制器。在Angularjs2中已经抛弃了module,ES6也引入了javascript底层的模块化。在模块化这方面,不必按照Angularjs 1.X铺好的路走。

在项目中,我们的做法是,整个单页面应用是一个module,每个页面对应一个controller和view,公共的功能写在service中(这点还需要改进,呵呵)。
    controller的定位应该是一个完整且尽可能小的功能模块。比如一个列表页,点击某条记录后弹窗显示该记录的详细信息,那么列表页写一个controller,详细页写另一个controller。controller之间是低耦合的,如果有一定的依赖关系,使用事件广播与接收进行通讯($emit, $broadcast, $on)。controller是不可复用的。
    公共的逻辑写在service中,并且按功能分类,满足单一职责。使用时用依赖注入。避免写成全局的公共方法。

五.懒加载

单页面应用如果体量较小,完全不需要懒加载,把所有脚本打包压缩在一起是更好的解决方案。但是体量较大,加载的脚本又多又大,就需要考虑懒加载的方式了。按需加载文件,而不是一次性加载整个应用所需要的全部文件。懒加载的方式推荐用ocLazyLoad,而不要用requireJs。因为requireJs只能加载文件,无法注册module,controller,directive,而ocLazyLoad不但可以加载文件,也可以完成注册。配合ui-route的路由管理,实现懒加载非常方便。

六.性能

Angularjs采用脏检测的方式来检查对象的变化,与其他框架相比——比如同为MVVM模式的vue.js或者使用了虚拟dom的React——Angularjs的性能并不出众。但是,开发一个单页面应用或者一个管理系统,性能完全不是瓶颈。造成Angularjs性能降低的关键因素往往是添加了太多的watcher,超过2000(经验数值)个watcher时,会明显降低性能。所以提高性能的基本方法就是尽量减少watcher数量,比如使用ng-repeat时限制数组的长度并使用track by,以及一次性数据绑定{{::x}}

七.安全

AngularJs本身不允许不安全的代码,比如controller中定义一段带有html标签的字符串:
$scope.html="<p>text</p>";
在页面上显示的是原始的字符串,而不是一个段落。这是Angularjs自身的防XSS攻击机制。除此另外,作为开发人员,应该注意不要在模版中动态签入用户输入的数据。当然,如果需要显示html编码后的内容,也是可以的,使用$sanitize或$sce服务即可。$sanitize会按照Angularjs自身设置的白名单来净化html,$sce服务包含有$sce.trustAs,$sce.trustAsHtml,$sce.trustAsUrl,$sce.trustAsResourceUrl,$sce.trustAsJs等方法,用于编码可信任的html标签。

总结:Angularjs作为当前流行的MVVM框架,开发管理类的CRUD系统真的太合适了。Javascript中一切皆对象,而在Angularjs中可以说一切皆数据,以数据驱动的方式解决dom的更新,提升不少开发效率。本次项目只是Angularjs的首次应用,只接触到了框架本身的部分功能,希望以后能有更多项目应用Angularjs。另外,Angularjs2已经在9月15日正式发布了,也许某天可以用Angularjs2来开发新的项目~

 
分类: AngularJs

AngularJs项目的更多相关文章

  1. 使用Yeoman快速启动AngularJS项目开发

    本博客停止更新,请访问新个人博客:owenchen.net 前言 博客迁移到了BAE上,http://owenchen.net/,以后的文章会首发在自己的博客上,随后在博客园发布. 很久没有写文章了, ...

  2. 【转】Yeoman自动构建 Angularjs 项目

    Yeoman是什么? Yeoman按照官方说法,它不只是一个工具,还是一个工作流.它其实包括了三个部分yo.grunt.bower,分别用于项目的启动.文件操作.包管理. Yo: Yo是一个项目初始化 ...

  3. angularJs项目实战!02:前端的页面分解与组装

    自从上一篇文章到现在已经有将近一个月的时间,我将精力放在了前端页面分解与组装,和angularjs如何与jquery.bootstrap.D3等一系列其他类库结合使用的经验总结上.由于公司新招了一些员 ...

  4. angularJs项目实战!01:模块划分和目录组织

    近日来我有幸主导了一个典型的web app开发.该项目从产品层次来说是个典型的CRUD应用,故而我毫不犹豫地采用了grunt + boilerplate + angularjs + bootstrap ...

  5. 使用Spring Boot和Gradle创建AngularJS项目

    Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的 ...

  6. AngularJS进阶(三十六)AngularJS项目开发技巧之利用Service&Promise&Resolve解决图片预加载问题(后记)

    AngularJS项目开发技巧之利用Service&Promise&Resolve解决图片预加载问题(后记) 前言 在"AngularJS项目开发技巧之图片预加载" ...

  7. AngularJS进阶(三十一)AngularJS项目开发技巧之获取模态对话框中的组件ID

    AngularJS项目开发技巧之获取模态对话框中的组件ID 需求 出于项目开发需求,需要实现的业务逻辑是:药店端点击查看"已发货""已收货"订单详情时,模块弹出 ...

  8. AngularJS进阶(三十)AngularJS项目开发技巧之图片预加载

    AngularJS项目开发技巧之图片预加载 绪 项目(移动端采用Ionic 框架)开发完毕,测试阶段发现移动APP首页的广告图片(图片由服务器端返回相应url地址)很难加载,主要原因还是网速.如下图左 ...

  9. AngularJS进阶(二十九)AngularJS项目开发技巧之localStorage存储

    AngularJS项目开发技巧之localStorage存储       注: localStorage深度学习 绪 项目开发完毕,测试阶段发现后台管理端二维码生成有问题,问题在于localStora ...

随机推荐

  1. iOS之pch文件的正确使用

    在Xcode6之前,创建一个新工程xcode会在Supporting files文件夹下面自动创建一个“工程名-Prefix.pch”文件,也是一个头文件,pch头文件的内容能被项目中的其他所有源文件 ...

  2. MySQL提供的错误日志中的错误级别一共有3个分别为:

    ERROR_LEVEL-->错误级别 WARNING_LEVEL-->警告级别 INFORMATION_LEVEL-->信息级别

  3. 关于SpringAOP的XML方式的配置

    AOP(XML)[理解][应用][重点] 1.AOP基础实例 A.导入jar包 核心包(4个)         日志(2个)             AOP(4个) Spring进行AOP开发(1个) ...

  4. PeopleReady--办公学习类App产品

    PeopleReady是能使人(公司或组织里的员工)快速Ready(经验+知识)的学习系统.对员工的好处是:- 可以迅速Ready,尽快符合岗位要求,尽快有Performance,尽快对公司有价值,从 ...

  5. 【linux操作命令】mysql

    1.linux下启动mysql的命令: mysqladmin start /ect/init.d/mysql start (前面为mysql的安装路径) 2.linux下重启mysql的命令: mys ...

  6. Metadata file not found - Data.Entity.Model

    错误 3 正在编译转换: 未能找到元数据文件“F:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\..\IDE\Micr ...

  7. sql的游标使用(转)

    游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合的.而游标打破了这一规则,游标使得我们思考方式变为逐行进行.对于类C的开发人员来着,这样的思考方式会更加舒服. 正常面向集合的思维方式是: ...

  8. Oracle之初始创建scott/tiger来测试

    在redhat5.5(32bit)上安装好oracle11g数据库软件,然后安装一个数据库,再然后登录数据库,创建scott/tiger测试 首先登录数据库,这里登录时是没有启动数据库的 [oracl ...

  9. touches,motion触摸事件响应

    //触摸事件响应需要重写方法 1 // 触摸时触发该方法(消息发送) - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent: ...

  10. WPF嵌入百度地图完整实现

    无论是做App还是web开发,很多都会用到地图功能,一般都会调用第三方的API实现地图功能!而正如国内的地图API提供方,基本上对Android.IOS和web开发提供了很完整的一套API,但是对于桌 ...