AngularJs项目

时间:2022-09-11 07:29:29

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的改进版,但是性能上是存在问题的,根据*上的问答,一个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)">

AngularJs项目

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

三.页面防抖动

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

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

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中,并且按功能分类,满足单一职责。使用时用依赖注入。避免写成全局的公共方法。

AngularJs项目

五.懒加载

单页面应用如果体量较小,完全不需要懒加载,把所有脚本打包压缩在一起是更好的解决方案。但是体量较大,加载的脚本又多又大,就需要考虑懒加载的方式了。按需加载文件,而不是一次性加载整个应用所需要的全部文件。懒加载的方式推荐用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进阶&lpar;三十六&rpar;AngularJS项目开发技巧之利用Service&amp&semi;Promise&amp&semi;Resolve解决图片预加载问题&lpar;后记&rpar;

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

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

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

  8. AngularJS进阶&lpar;三十&rpar;AngularJS项目开发技巧之图片预加载

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

  9. AngularJS进阶&lpar;二十九&rpar;AngularJS项目开发技巧之localStorage存储

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

随机推荐

  1. 配置SVN、GIT总结

    SVN使用说明 svn地址(可以是内网,也可以是外网的):svn://192.168.3.1/xxxhttp://192.168.3.1/xxxhttps://192.168.3.1/xxx 一个sv ...

  2. Android应用中使用AsyncHttpClient来异步网络数据(转载)

    摘要: 首先下载AsyncHttpClient的库文件,可以自行搜索,可以到下面地址下载 http://download.csdn.net/detail/xujinyang1234/5767419 测 ...

  3. Linux之线程管理

    linux下查看线程数的几种方法   1. cat /proc/${pid}/status [root@limt01 2325]# ps -ef|grep xinetd|grep -v grep ro ...

  4. USACO Section 2&period;4&colon; Overfencing

    这题因为各种琐事耽耽搁搁做了2天,也出了挺多错误,最后出了一个结论:像这种有对neighbor有通路的图形用一个4个位表示4个方向的int进行位运算比较靠谱. /* ID: yingzho1 LANG ...

  5. c&plus;&plus; 常用数据接口 set

    #include <set> #include <iostream> #include <string> int main(void) { std::set< ...

  6. 利用花生壳在自己电脑上建立外网可访问的svn

    下载花生壳并注册账号 2.花生壳会送你一个免费的二级域名 3.登陆到路由器界面192.168.0.1或者192.168.0.0进入动态dns选项输入你的花生壳账号密码 4.在路由器设置界面设置转发规则 ...

  7. 013实现使用两个堆栈队列&lpar;keep it up&rpar;

    实现使用两个堆栈队列 FIFO队列是一种数据结构(FIFO),后堆叠前进出的数据结构的(FILO).  两个栈实现的最简单的方法就是排队:队列中的第一个推栈,  队列将数据顺序的第一个堆栈推入第二堆叠 ...

  8. 在页面中有overflow-y&colon;auto属性的div&comma;当出现滚动条,点击返回顶部按钮,内容回这个div最顶部

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. input禁止输入空格

    <input name="" onkeyup="this.value=this.value.replace(/^\s+|\s+$/g,'')" value ...

  10. 【Spark深入学习-11】Spark基本概念和运行模式

    ----本节内容------- 1.大数据基础 1.1大数据平台基本框架 1.2学习大数据的基础 1.3学习Spark的Hadoop基础 2.Hadoop生态基本介绍 2.1Hadoop生态组件介绍 ...