使用AngualrJs开发移动App已经快半年了,逐渐积累了非常多AngularJS的问题,特别是对于用惯了Jquery的开发人员,转到AngularJS还是须要克服非常多问题的。不像Jquery那样側重DOM操作,AngularJS是以视图模型和双向绑定为核心的。

以下的内容如果你已经了解前端 MVC 概念,并对 AngularJS 有了一定经验,刚開始学习的人读起来可能比較艰深晦涩。本文的总结会涉及部分在移动设备上特有的问题。

DOM操作的问题

避免使用 jQuery 来操作 DOM,包含添加元素节点,移除元素节点,获取元素内容,隐藏或显示元素。你应该使用 directives 来实现这些动作,有必要的话你还要编写自己的 directives。

在站点Web前端开发中,假设你感到非常难改变习惯,那么考虑从你的网页中移除 jQuery 吧。真的,AngularJS 中的 $http 服务非常强大,基本能够替代
jQuery 的 ajax 函数,并且 AngularJS 内嵌了 jQLite —— 它内部实现的一个 jQuery 子集,包括了经常使用的 jQuery DOM 操作方法,事件绑定等等。但这并非说用了AngularJS 就不能用 jQuery 了。假设你的网页有加载 jQuery 那么 AngularJS 会优先採用你的 jQuery,否则它会 fall back 到 jQLite。

假设是移动App或移动Web开发,建议不要引入Jquery了,假设实在须要jquery的某些功能,引入Zepto.js吧。只是请相信我,用了AngularJS,你不会须要Jquery的!

须要自己编写 directives 的情况一般是当你使用了第三方的 jQuery 插件。由于插件在 AngularJS 之外对表单值进行更改,并不能即时反应到 Model 中。比如我们用得比較多的 jQueryUI datepicker 插件,当你选中一个日期后,插件会将日期字符串填到
input 输入框中。View 改变了,却并没有更新 Model,由于$('.datepicker').datepicker(); 这段代码不属于 AngularJS 的管理范围。我们须要编写一个directive 来让 DOM 的改变即时更新到 Model 里。

var directives = angular.module('directives', []);

directives.directive('datepicker', function() {
return function(scope, element, attrs) {
element.datepicker({
inline: true,
dateFormat: 'dd.mm.yy',
onSelect: function(dateText) {
var modelPath = $(this).attr('ng-model');
putObject(modelPath, scope, dateText);
scope.$apply();
}
});
}
});

然后在 HTML 中引入这个 directive

<input type="text" datepicker ng-model="myObject.myDateValue" />

Directive
就是在 HTML 里写自己定义的标签属性,达到插件的作用,有效补充了HTML的功能。这样的声明式的语法扩展了 HTML。建议项目中通用的功能和页面组件,都封装成Directive,方便使用和代码维护。

须要说明的是,有一个 AngularUI 项目提供了大量的 directive 给我们使用,包含 Bootstrap 框架中的插件以及基于
jQuery 的其它非常热门的 UI 组件。 AngularJS 的社区如今非常活跃,生态系统健全。

ngOption 中的 value

这是个大坑。假设你去查看 ngOption 生成的 <select> 中的 <option> 的选项值(每一个 <option
value="xxx">
 的 value 部分),那绝对是枉费心机。由于这里的值永远都会 是 AngularJS 内部元素的索引,并非你所指定的表单选项值。

还是要转变观念,AngularJS 已经不再用表单进行数据交互了,而是用 Model。使用 $http 来提交 Model,在 php 中则使用 file_get_contents('php://input') 来获取前端提交的数据。

Input type='number'的问题

AngularJS有些版本号,当输入框设为 Input
type='number'时,在移动设备上ng-change方法会失效。

{{ }} 的问题

在页面初始化的时候,用户可能会看到 {{ }},然后闪烁一下才出现真正的内容。

解决的方法:

  1. 使用 ng-cloak directive 来隐藏它
  2. 使用 ng-bind 替代 {{ }}

将界面与业务逻辑分离

Controller 不应该直接引用 DOM,而应该控制 view 的行为。比如“假设用户操作了 X,应该发生什么事情”,“我从哪里能够获得 X?”

Service 在大部分情况下也不应该直接引用 DOM,它应该是一个单例(singletons),独立于界面,与 view 的逻辑无关。它的角色仅仅是“做 X 操作”。

DOM 操作应该放在 directives 里面。

尽量复用已有功能

你所写的功能非常可能 AngularJS 已经实现了,有一些代码是能够抽象出来复用的,使用更 Angular 的方式。总之就是非常多 jQuery 的繁琐代码能够被替代。

1. ng-repeat

ng-repeat 非常实用。当 Ajax 从server获得数据后,我们常常使用 jQuery (比方上面讲过的样例) 向某些 HTML 容器节点中加入很多其它的元素,这在 AngularJS 里是不好的做法。有了 ng-repeat 一切就变得非常easy了。在你的 $scope 中定义一个数组 (model) 来保存从server拉取的数据,然后使用 ng-repeat 将它与 DOM 绑定就可以。以下的样例初始化定义了 friends 这个 model

<div ng-init="friends = [{name:'John', age:25}, {name:'Mary', age:28}]">
I have {{friends.length}} friends. They are:
<ul>
<li ng-repeat="friend in friends">
[{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
</li>
</ul>
</div>

2. ng-show

ng-show 也非常实用。使用 jQuery 来依据条件控制界面元素的显示隐藏,这非经常见。可是 Angular 有更好的方式来做到这一点。ng-show (以及 ng-hide) 能够依据布尔表达式来决定隐藏和显示。

对于数组或字符串,能够用strXXXX.length控制显示,否则在移动设备上会不正常。

类似的内置 directives 还有 ng-disabled, ng-switch 等等,用于条件控制,语法简洁,都非常强大。

3. ng-class

ng-class 用于条件性地给元素加入 class,曾经我们也经经常使用 jQuery 来实现。Angular 中的 ng-class 当然更好用了,样例:

<div ng-class="{ errorClass: isError, warningClass: isWarning, okClass: !isError && !isWarning }">...</div>

在这里 ng-class 接受一个 object 对象,key 为 CSS class 名,值为 $scope 变量控制的条件表达式,其它类似的内置 directives 还有 ng-class-even 和 ng-class-odd,非常有用。

ng-show和ng-if的使用场景问题

使用ng-show和ng-if都实现控制页面元素显示的功能,但2者是不同的,ng-if会动态创建DOM,ng-show仅仅是切换已有DOM的显示,相当于设置style="display:none",假设使用before和after等css伪类控制显示效果,可能会出现故障,须要依据情况合理使用ng-show和ng-if。

$watch 和 $apply

AngularJS 的双向数据绑定是最令人兴奋的特性了,然而它也不是全能的魔法,在某些情况下你须要做一些小小的修正。

当你使用 ng-model, ng-repeat 等等来绑定一个元素的值时, AngularJS 为那个值创建了一个 $watch,仅仅要这个值在 AngularJS 的范围内有不论什么改变,全部的地方都会同步更新。而你在写自己定义的 directive 时,你须要定义你自己的 $watch 来实现这样的自己主动同步。

有时候你在代码中改变了 model 的值,view 却没有更新,这在自己定义事件绑定中常常遇到。这时你就须要手动调用 scope.$apply() 来触发界面更新。上面 datepicker 的样例已经说明了这一点。第三方插件可能会有 call back,我们也能够把回调函数写成匿名函数作为參数传入$apply()中。

将 ng-repeat 和其它 directives 结合起来

ng-repeat 非常实用,只是它和 DOM 绑定了,非常难在同一个元素上使用其它 directives (比方 ng-show, ng-controller 等等)。

假设你想对整个循环使用某个 directive,你能够在 repeat 外再包一层父元素把 directive 写在那儿;假设你想对循环内部的每个元素使用某个 directive,那么把它放到 ng-repeat 的一个子节点上就可以。

Scope的问题

Scope 在 templates 模板中应该是 read-only 的,而在 controller 里应该是 write-only 的。Scope 的目的是引用 model,而不是成为 model。model 就是我们定义的 JavaScript 对象。

$rootScope 是能够用的,只是非常可能被滥用

Scopes 在 AngularJS 中形成一定的层级关系,树状结构必定有一个根节点。通常我们用不到它,由于差点儿每一个 view 都有一个 controller 以及相相应的自己的 scope。

但偶尔有一些数据我们希望全局应用在整个 app 中,这时我们能够将数据注入 $rootScope。由于其它 scope 都会继承 root scope,所以那些注入的数据对于 ng-show 这类 directive 都是可用的,就像是在本地 $scope 中的变量一样。

当然,全局变量是邪恶的,你必须非常小心地使用 $rootScope。特别是不要用于代码,而只用于注入数据。假设你非常希望在 $rootScope 写一个函数,那最好把它写到 service 里,这样只实用到的时候它才会被注入,測试起来也方便些。

相反,假设一个函数的功能不过存储和返回一些数据,就不要把它创建成一个 service。

子作用域的原型继承问题

对于刚開始学习的人,这个也是个大坑啊。作用域变量的继承是基于javascript原型继承机制的,在使用涉及到作用域的指令如ng-template,ion-modal等时须要特别注意,相关的查找顺序这里就不细说了。

AngularJS移动开发中的坑汇总的更多相关文章

  1. [转]AngularJS移动开发中的坑汇总

    使用AngualrJs开发移动App已经快半年了,逐渐积累了很多AngularJS的问题,特别是对于用惯了Jquery的开发者,转到AngularJS还是需要克服很多问题的.不像Jquery那样侧重D ...

  2. AngularJS移动开发中的各种坑

    捂脸,辛酸泪ing...... 本文主要涉及部分在移动设备上特有的问题. 相对来说,Jquery侧重DOM操作,AngularJS是以视图模型和双向绑定为核心的. DOM操作的问题 避免使用 jQue ...

  3. Unity3d Android Http 开发中的坑(吐槽

    在一般的U3D网络开发中,直接使用WWW类便足够正常使用,但我在发现使用WWW下载大文件时,会导致整个程序卡顿的情况(不清楚是否我个人电脑问题),所以干脆使用HttpWebRequest/HttpWe ...

  4. Java技术开发中的坑

    1.(2014/05/28)struts2中使用eclipse自动获取getter和setter方法的坑 今天着实被eclipse坑了一把,平时遇到get和set方法时,我都是通过eclipse自动生 ...

  5. JavaWeb开发中遇到问题汇总

    一.基础问题 1.${pageContext.request.contextPath}获取相对路径无效 问题:在jsp中使用${pageContext.request.contextPath}获取相对 ...

  6. [Android Studio篇][1] AS开发中遇到问题汇总

    1 在android新建文件,提示权限不够,增加权限 修改工程下 main/AndroidMainfest.xml增加 <uses-permission android:name="a ...

  7. Android开发遇到的坑(1):Java中List的安全删除问题

    在项目的开发过程中,一定少不了的是对Java集合中的List接触.项目中对List的删掉也是一种常见的操作,看上这个操作也没什么好说的样子,但是在项目开发中也是最容易出错的地方,特别是对于新手.有时候 ...

  8. Ionic2 + Angular4 + JSSDK开发中的若干问题汇总

    前景 目前微信公众号程序开发已经相当火热,客户要求自己的系统有一个公众号,已经是一个很常见的需要. 使用公众号可以很方便的便于项目干系人查看信息和进行互动,还可以很方便录入一些电脑端不便于录入的数据, ...

  9. Java 开发中如何正确踩坑

    为什么说一个好的员工能顶 100 个普通员工 我们的做法是,要用最好的人.我一直都认为研发本身是很有创造性的,如果人不放松,或不够聪明,都很难做得好.你要找到最好的人,一个好的工程师不是顶10个,是顶 ...

随机推荐

  1. window成员和document成员

    输出浏览器成员和DOM成员(以下为safari浏览器测试)(浏览器不同对象成员有差异) window成员 <script type="text/javascript"> ...

  2. cordova热更新

    cordova 热更新: 一.添加插件 1.新建Cordova项目 cordova create CordovaHotCode com.ezample.hotcode 2.添加Android平台 在新 ...

  3. Facebook登录 AndroidStudio

    简介 主页:https://www.facebook.com/ Android开发者支持:https://developers.facebook.com/docs/android/  应用管理:htt ...

  4. Resharper

    http://baike.baidu.com/link?url=H8DVtrvKV1Cg-Hrz82C6ZiJOUXbi_3BfoROe-RlHhctPna4-BFfglPh2OsR-KmCqRZ7_ ...

  5. C/C++中的浮点数运算

    代码: #include <iostream> #include <cstdio> #include <cfloat> using namespace std; i ...

  6. POJ1276:Cash Machine(多重背包)

    Description A Bank plans to install a machine for cash withdrawal. The machine is able to deliver ap ...

  7. win32 console application 如何修改图标?

    win32 console application ,不要看这名字高端大气上档次,让你摸不着头脑,其实他就是我们最先学习c语言那种黑色窗口的东西......话说他怎么修改图标呢?第一种方法是:右键-〉 ...

  8. JS通用表单验证函数,基于javascript正则表达式

    表单的验证在实际的开发当中是件很烦琐又无趣的事情今天在做一个小项目的时候,需要JS验证,寻找到一个比较好的东西 地址如下: http://blog.csdn.net/goodfunman/archiv ...

  9. Android再学习-20141023-Intent-Thread

    20141023-Android再学习 Intent对象的基本概念 Intent是Android应用程序组件之一 Intent对象在Android系统中表示一种意图 Intent当中最重要的内容是ac ...

  10. C 小写字母编程大写并输出

    main(){ FILE *fp; char str[100],filename[10]; int i=0;if((fp=fopen("test","w"))= ...