那些年,在AngularJS的路上遇到的坑
使用AngularJS这么久以来,遇到过一些坑,之前一直没有以书面的形式整理下,现在好好总结下,以供后面查备。
一、angular scope 在ng-if与ng-show下的区别(两者作用域的差别)
以下代码为一个针对应用列表分页的代码:
HTML代码:
对应的js代码为:
在页面中我们可以看到效果:
可以看到:在使用ng-if时,点击分页时,在ng-if包括的作用域里,$scope.currentPage的值改变了,但是ng-if所在作用域外面,打印$scope.currentPage的值时,仍然不变,始终是初始化的状态,并且可以看到获取的列表也并没有改变。
解决方案:将ng-if换为ng-show,或者ng-model=”currentPage”改为ng-model=”parentObj.currentPage”,下面看看解决之后的效果:
可以看到,选择分页时,页码相应的改变了,获得列表也正确了。
为什么会出现上述情况呢?小编在http://camnpr.com/javascript/1888.html和http://stackoverflow.com/questions/21869283/when-to-favor-ng-if-vs-ng-show-ng-hide??这两个地方找到了答案,究其原因就是ng-if 指令像其它指令一样,会创建一个子域(child scope)。
因此,ng-if里的ng-model的$scope是子域下的,外部作用域无法捕获$scope的更新值,而ng-show则是作用于外部作用域的。
综上,ng-if与ng-show的原理是不一样的:
1、ng-show/ng-hide是通过修改CSS样式方式控制元素显示与隐藏,对应的DOM元素会一直存在于当前页面中,而ng-if根据表达式的值动态的在当前的页面中添加删除页面元素。如果赋值表达式的值为false,那么这个元素就会从页面中删除,否则会添加一个元素。ng-if创建元素时用的是被它编译后的代码,如果ng-if内部的代码被其它方式修改过,那么修改只会对本次展现有效,页面元素重新渲染后修改效果会消失,而ng-show/ng-hide则能够保留dom元素上次修改后的状态。
2、作用域不同:当一个元素被ng-if从DOM中删除时,与其关联的作用域也会被销毁。而且当它重新加入DOM中时,则会生成一个新的作用域,而ng-show和ng-hide则不会。
二、UI闪烁问题
众所周知,Angular最大的亮点就是数据的双向绑定。然而,在项目的实际使用过程中,往往会碰到页面闪现出没有被解析的表达式(形如{{app.name}})。是因为在Angular初始化之前,DOM还没准备就绪,Angular正在计算并替换相应的值。
解决办法:
1、放弃使用{{ }}表达式,改用ng-bind指令;
2、在元素上添加“ng-clock”,工作原理就是在初始化阶段inject了css规则,或者你可以包含这个css 隐藏规则到你自己的stylesheet。Angular就绪后就会移除这个cloak样式,让我们的应用(或者元素)立刻渲染。
三、ng-include指令
<div ng-include="views/include/footer.html"></div> 错在哪里,记得在第一次使用ng-include的时候,这样引用文件,始终在页面上都不显示footer.html的内容,后来明白ng-include需要的是一个变量,所以我们可以改写成<div ng-include="’views/include/footer.html’"></div> 或定义一个$scope变量,如:$scope.footerHtml="views/include/footer.html"; 页面引用:<div ng-include="footerHtml"></div>。效果如下图所示:
究其原因是:因为在ng-include中,是把它的参数当做变量来解释的,它会通过$eval对传入的值进行计算,然后作为模板地址去加载。
不过,更好的方法是把这些界面片段(partical)写成指令,那样你就不用在多处重复写路径了,更重要的是,将来你可以直接在这里扩展它的交互逻辑,从界面原型平滑的演化到线上系统。
下面举一个写成指令的例子:
HTML页面:页面中直接使用指令,指令会找到对应的页面进而进行DOM的渲染。
directive指令:
四、angularJS文件压缩问题
当项目上线时,我们往往需要将文件压缩以减少体积来提高页面的加载速度,普通的javascript压缩一般都没什么问题,但是如果是以下格式编码的angularJS文件压缩后,在使用则会报错:
解决办法是:使用Javascript数组方式构造控制器:把要注入的服务放到一个字符串数组(代表依赖的名字)里,数组最后一个元素是控制器的方法函数:
varBookCtrl = ['$scope', '$http', function($scope, $http) { /* constructor body */}];
如以下登陆的controller:
这样使用数组的方式在压缩后,就不会出现依赖的错误了。
五、IE11下get请求缓存问题,页面绑定数据不及时更新的bug
在项目开发的过程中,我曾经发现过一个奇葩的问题,就是在IE11浏览器下,当点击某个button触发一个函数,从而改变ng-model绑定的某个变量时,明确变量的值已经改变,但是只有在F12开启开发者调试工具时,页面才能及时更新显示改变后的变量值,一旦F12开发者调试工具关闭,变量值将不更新。但是这一现象在chrome、firefox下确不曾见,究其原因竟是IE浏览器下ajax请求缓存的问题,后来把缓存禁用后,竟恢复正常了。具体解决方法就是:在配置路由的angularJS文件中,添加如下配置代码即可:
六、angular中的unsafe问题
在项目中,之前遇到过这样的问题,就是当给一个ios应用上传安装包和plist文件后,一般这个ios应用的下载地址就会变为:
“itms-services:///?action=download-manifest&url=https://dn-touchc-test.qbox.me/test2.plist”这样的样子,但是当我们把这样的字符串放到<a>标签的href属性中时,其会自动在上述字符串之前加上“unsafe:”的字符串:如下图所示:
而这个这样加了“unsafe:”字样的链接被我们复制到手机浏览器里进行下载则会报找不到。
解决办法就是:在angular配置路由的配置文件中加入如下配置代码:
再来看结果:
原来angular对href是有安全检查的,只能生成它认为安全的链接。AngularJS真是为我们的安全操碎了心……而我也更加明白了{{}}并不是一个简单的模板替换,它真的把我们的html重新编译了一遍。
七、使用ng-repeat或ng-options进行数据循环时,track by的使用
在使用ng-repeat进行数据循环时,如果后端数据库采用的是moogodb的话,当 ng-repeat 的数组被替换时, 它默认并不会重新利用已有的 Dom 元素,而是直接将其全部删除并重新生成新的数组 Dom 元素,Dom 的频繁操作是非常不友好的,为什么 ng-repeat 不能利用已有的 dom 元素去更新数据呢?因为你没有把数组元素的标识属性告诉它,那么两次替换的时候它就没办法追踪了,所以当首次使用ng-repeat渲染出列表数据,再次请求渲染数据的时候,ng-repeat会往数组中每个元素加上$$hashKey属性,这个 key 是由 Angular 内部的 nextUid() 方法生成,类似数据库自增,但是是使用字符串。因此,我们使用 track by 来避免,例如:
$index表示默认的索引(自动递增),item.id是数据的主键值。
八、$apply的使用
之前在微信端修改个人设置的页面时,接口没有返回用户的相关信息,只有通过另一个接口去获取用户的具体信息,但是这个过程中发现拿到用户的具体信息重新给$scope.userData赋值后,虽然model值改变了,但是页面并没有及时更新,主要原因是angular没有检测到数据变化,所以此时需要我们手动通知angular数据改变,如下代码所示:

这里使用的是$apply的无参数形式,另外还有一种形式是:

这样也可以,$scope.$apply() 会自动触发 $rootScope.$digest(),从而让 watchers 被触发用以更新view。具体可以参考这篇文章:深入理解Angular中的$apply()以及$digest()。
当然,后面的路还很长,遇到的坑也不止这些,我会持续更新的……
那些年,在AngularJS的路上遇到的坑的更多相关文章
- 【转】8年!我在OpenStack路上走过的坑。。。
8年!我在OpenStack路上走过的坑... 摘要: 2010年10月,OpenStack发布了第一个版本:上个月,发布了它的第18个版本Rocky.几年前气氛火爆,如今却冷冷清清.Rocky版本宣 ...
- AngularJS移动开发中的坑汇总
使用AngualrJs开发移动App已经快半年了,逐渐积累了非常多AngularJS的问题,特别是对于用惯了Jquery的开发人员,转到AngularJS还是须要克服非常多问题的.不像Jquery那样 ...
- 关于angularjs在IE里的坑——F12工具打开,功能正常,关闭之后,angularjs not working
前端时间在做项目的时候,用到了angularjs,期间,发现了一个奇葩的问题,就是在IE11浏览器下,点击下方图1上箭头所示的位置,将此处的开关变为图2中箭头所示的样子,但是发觉没有反应,开关还是灰色 ...
- [转]AngularJS移动开发中的坑汇总
使用AngualrJs开发移动App已经快半年了,逐渐积累了很多AngularJS的问题,特别是对于用惯了Jquery的开发者,转到AngularJS还是需要克服很多问题的.不像Jquery那样侧重D ...
- Angularjs里面跨作用域
Angularjs里面跨作用域的实战! 好久没有来写博客了,最近一直在用Google的AngularJS,后面我自己简称AngularJS就叫AJ吧! 学习AngularJS一路也是深坑颇多啊-- ...
- Angularjs里面跨作用域的实战!
好久没有来写博客了,最近一直在用Google的AngularJS,后面我自己简称AngularJS就叫AJ吧! 学习AngularJS一路也是深坑颇多啊--!就不多说了,不过还是建议大家有时间去学下下 ...
- AngularJS常见面试题
本文引自:https://segmentfault.com/a/1190000005836443 问题来源:如何衡量一个人的 AngularJS 水平? ng-if 跟 ng-show/hide 的区 ...
- AngularJS 常见面试问题
ng-if 跟 ng-show/hide 的区别有哪些? 第一点区别是,ng-if 在后面表达式为 true 的时候才创建这个 dom 节点,ng-show 是初始时就创建了,用 display:bl ...
- 关于python数据序列化的那些坑
-----世界上本来没那么多坑,python更新到3以后坑就多了 无论哪一门语言开发,都离不了数据储存与解析,除了跨平台性极好的xml和json之外,python要提到的还有自身最常用pickle模块 ...
随机推荐
- Java学习日记之 Java-其他类型
OK , 就绪, 第一篇博客开撸 ~ 先听了毕姥爷激情澎湃的其他类型 ,从这里开始入手吧 : (一)System类 System类代表系统类,系统的属性和方法都放在该类.System类是一个fina ...
- CentOS 7 安装 vmware-tools
[原创]标题:<CentOS 7 安装 vmware-tools>:作者:肖雪峰,QQ:35360657. 用 VMware Workstation 11 新安装了CentOS 7虚拟机, ...
- 项目文件""已被重命名或已不在解决方案中
如题,这个错误在vs2010里,开始编译的时候出现了,我的解决办法就是把所有的project都移除,然后再添加进来,就不弹这个错误了.
- WIN8 隐私声明
隐私权声明 本应用连接网络仅为控制硬件设备,不会收集你的个人信息,也不共享你个个人信息. 应用名称 CrossMedia可视化控制系统(服务器版) 关于本应用 本应仅为控制设备应用,不关注任何配置相关 ...
- Jexus web server V5.4.5 已经发布
Jexus 是运行于 Linux/FreeBSD 平台的一款以支持 ASP.NET 为主要特色的,同时非常重视安全性和稳定性的高性能 WEB 服务器.最新版 5.4.5 已经发布,官方网站是:www. ...
- Backbone源码解析(一):Event模块
Backbone是一个当下比较流行的MVC框架.它主要分为以下几个模块: Events, View, Model, Collection, History, Router等几大模块.它强制依赖unde ...
- 软件测试基本理论-IBM模式
软件测试基本理论(1) IBM生产模式 1 参考书目 <IBM-从菜鸟到测试架构师-一个测试工程师的成长日记> 出版社:电子工业出版社 印次:2013年6月 作者:IBM主要工程师 2 ...
- Nim语言的模块化编程
前言 Nim支持把一大段程序分成若干个模块 一个模块就是一个源代码文件 每个模块都拥有它自己的名称空间 模块化可以起到封装(信息隐藏)和分步编译的作用 一个模块可以通过import语句获得另一个模块的 ...
- UWP 统一平台开发介绍
什么是UWP? 很多程序员都有一个梦想:希望自己开发的软件能够轻而易举的在所有平台上运行,而不是把同样的需求,用不同的技术.工具重新开发才能够运行在所有平台上.这就是跨平台,很多软件从业者都在为这个梦 ...
- cxf restful
Restful 服务端 1 创建好pojo.dao.service, dao进行数据库操作,service提供服务 @Path("/roomservice") @Produces( ...