在Angular群里回答新手问题一段时间了,有一些Angular方面的坑留在这里备查,希望能对各位有所帮助。这个文章将来会随时更新,不会单独开新章,欢迎各位订阅。

Q1.<div ng-include="views/user/show.html"></div> 错在哪里?

如果你这么写过,会发现这个位置啥也没有加载出来,那么,错在哪里呢?错在ng-include需要的是一个变量,如果你在$scope中有这样一个变量 $scope.userShowTemplateUrl = "views/users/show.html",并且把上面这句变为<div ng-include="userShowTemplateUrl"></div>就能正常工作了。或者这样写也行:<div ng-include=" 'views/user/show.html' "></div>

原因何在?

因为在ng-include中,是把它的参数当做变量来解释的,它会通过$eval对传入的值进行计算,然后作为模板地址去加载。

不过,更好的方法是把这些界面片段(partical)写成指令,那样你就不用在多处重复写路径了,更重要的是,将来你可以直接在这里扩展它的交互逻辑,从界面原型平滑的演化到线上系统。

Q2. 我的指令怎么无效?

A2. 如果你排除了代码错误等问题,那么最可能的原因是restrict。restrict参数是用来规定你可以通过哪种方式来使用指令,而这个问题之所以容易 成为坑,是因为restrict的默认值是A,也就是说,默认情况下,指令只能通过属性的形式使用,比如我写了一个指令叫做appHeader,那么默认 情况下我只能用这样的形式使用它:<div app-header></div>,而<app-header></app-header>的形式则是无效的。

所以,如果你用返回函数的形式使用指令,那么你就只能使用属性的方式调用它,比如:

yourModule.directive('appHeader', function() {
return function(scope, element, attrs) {
element.text('hello');
}
});

如果要使用元素的方式使用指令,那么你就要这样写:

yourModule.directive('appHeader', function() {
return {
restrict: 'E', // 或'EA'等都可以,几种形式可以任意组合
link: function(scope, element, attrs) {
element.text('hello');
}
}
});

Q3. 修改了变量怎么界面没反应?

A3. 首先你当然要检查有没有错误以及是否确实是scope变量,如果这些都没问题,那么多半儿是$apply导致的。对于大多数操作,$apply都会自动执 行,所以你不用担心,但是如果你使用了angular之外的功能,比如直接调用了setTimeout函数、挂接了jquery的事件、使用了 jquery的ajax操作等等,那么系统就没有机会帮你调用$apply,界面也就没有机会刷新了,但是你如果之后又做了其他会导致$apply的操 作,你会发现以前“欠下”的那次界面刷新被正常执行了了 …… 迟到的刷新仍然是bug。

典型代码如下:

setTimeout(function() {
$scope.time = new Date()
}, 1000);

这种情况下你在页面中绑定的time变量将不会被自动刷新,无论是通过{{}}表达式,还是通过ng-*属性或者其他任何形式。怎么改呢?这样:

setTimeout(function() {
$scope.$apply(function() {
$scope.time = new Date();
});
}, 1000);

不过,这不是最好的形式,最好的形式是什么呢?当然是使用angular内置的$timeout服务,它就是干这个的:

$timeout(function() {
$scope.time = new Date();
});

没有$apply,却正常工作,没bug,而且漂亮多了吧?不过这里别忘了你得把$timeout服务进行依赖注入,不然它是undefined。

Q4. ng-click 写成 ng-class 导致的界面停止响应

A4. 这是我自己犯过的一个低级错误,属于深度依赖ide导致的问题。ide的自动代码提示功能,ng-cl的第一个候选项是ng-class,如果偷懒少打了 一个字,那么本来想写ng-click的代码就会写成ng-class,结果就是,无休止的重新计算ng-class中的表达式,其中的原因还没来得及看 源码研究。

如果遇到界面停止响应的问题,而且你也同样深度依赖ide,那么,从这个角度查查看吧。

Q5. 我知道你不拜金,但别忘了$

A5. 在angular中有一个通用的约定:angular的内部服务、方法、属性通常都会以$开头,而相应的,它也要求你自己的命名不要用$开头。比较容易忘 记用$开头的主要是一些方法,特别是$apply, $watch, $on, $broardcast, $emit这些,而这些如果你写错了,在chrome中你将得到一个莫名其妙的提示 TypeError: undefined is not a function! 可恶的是,连函数名字都没有!所以,虽然我知道你不拜金,但是千万不要忘了写$!

Q6. 注意作用域的原型继承问题!

A6. 在Angular中,作用域是通过原型链进行继承的。而这种继承有一个问题,那就是在子类中对变量进行赋值时,不会去修改父级的。

假设scopeA继承自scopeB,而在scopeB中定义了一个变量value: 1,这时候,读取scopeA.value可以正确取到值,但是如果赋值,就有问题了 scopeA.value = 2,这时候,scopeB.value的值是多少呢?你可能以为是2,但它是1!原因就在于原型继承时对变量的赋值不会修改原型中的值,而是直接在当前scope中创建一个同名的属性。

这个现象导致了一个容易让新手困惑的问题:

下面的代码工作正常:

<label><input type="radio" ng-model="color" value="red">  Red </label><br/>
<label><input type="radio" ng-model="color" value="green"> Green</label><br/>
<label><input type="radio" ng-model="color" value="blue"> Blue </label><br/> {{color}}

而下面的代码工作不正常,color值将不会随着选择而变化:

<div ng-repeat="value in ['red', 'green', 'blue']">
<label><input type="radio" ng-model="color" ng-value="value"> {{value}} </label>
</div>
{{color}}

它的原因就在于color值定义在当前scope中,而ng-repeat创建了一个子scope,它使用原型继承的方式从父级继承下来。对color值的修改,会去修改子级的变量,而父级的同名变量不会被修改。

要想让它正常工作,就改成这样:

<div ng-repeat="value in ['red', 'green', 'blue']">
<label><input type="radio" ng-model="vm.color" ng-value="value"> {{value}} </label>
</div>
{{vm.color}}

这里,把color定义成了一个vm对象的属性,这时候,因为只需要对vm的成员进行赋值,而不存在对vm进行赋值的情 况,所以赋值会正确的作用于父级scope上。这里的vm只是$scope上的一个对象,叫别的名字也可以,只是因为它的实际作用是ViewModel, 所以我习惯于把它命名为vm。

在Angular 1.2以后的版本中引入了controllerAs语法,可以一劳永逸的解决这个问题。具体的用法请参见 http://www.cnblogs.com/whitewolf/p/3493362.html

如果使用1.2以下的版本,可以在controller的第一句加上这样的语法来模拟:

var vm = $scope.vm = {};
所有的$scope变量都改为赋值给vm变量就可以了,view中也要相应的引用vm变量。

Q7. angular.module的两种写法:含义大不同

angular.module('name', [])angular.module('name') 虽然看起来很相似,但是!它们的含义却是截然不同的!

angular.module('name', [])是创建一个新的module,[]表示它没有依赖任何其他模块,如果已经有了一个同名模块,则会覆盖现有的。

angular.module('name')是查找一个现有module,如果这个module不存在,则返回空值。

如果把带方括号的形式(创建)误用为不带方括号的形式(引用),那么在它的返回值上调用controller等函数会出现空指针错误。

而如果把引用形式误用为创建形式,则会导致难以理解的“对象不存在”错误,但是你却明明定义过那个service或者controller等对象!这种问题就是因为后面的模块定义覆盖了以前的模块定义,你定义过的那些对象都被随着以前的module而丢掉了!

Q8. 第三方指令不起作用

最可能的原因是你没有加入模块依赖。第三方指令通常会定义在自己的模块中,所以这个模块必须被你的app模块所依赖,其中包含的指令才能在view中使用。比如你要使用ui-select2指令,就必须在自己的模块定义中加入这个依赖:

angular.module('app', [
'ngCookies',
'ngResource',
'ngSanitize',
'ui.select2'
]).....

如果仍然没有解决问题,请看看控制台中有没有错误信息,以及是否存在Q2所提的情况。

Angular新手容易碰到的坑的更多相关文章

  1. Angular 新手容易碰到的坑

    Q1.<div ng-include="views/user/show.html"></div> 错在哪里? 如果你这么写过,会发现这个位置啥也没有加载出来 ...

  2. 原创:Angular新手容易碰到的坑,随时更新,欢迎订阅

    在Angular群里回答新手问题一段时间了,有一些Angular方面的坑留在这里备查,希望能对各位有所帮助.这个文章将来会随时更新,不会单独开新章,欢迎各位订阅. Q1. <div ng-inc ...

  3. angular环境搭建时的坑

    安装angular环境踩过一些坑,最终还是把工程跑起来了,这里描述一下我的步骤,不排除有些步骤是多余的,希望能对遇到同样问题的小伙伴有帮助. 下载最新版node.js. 安装node,安装过程一路点下 ...

  4. Angular测试遇到的小坑

    Angular测试遇到的小坑 Error: Expected to be running in 'ProxyZone', but it was not found 检查doneFn的写法是否正确,位置 ...

  5. 那些在BAE上部署node.js碰到的坑

    在BAE上使用node.js半年多了,其中碰到了不少因为BAE云环境限制碰到的坑 写下来大家碰到了,也不用那么麻烦的去看好几天代码了,直接对症下药 官方公布的坑有: BAE是使用package.jso ...

  6. spring boot -- 无法读取html文件,碰到的坑

    碰到的坑,无法Controller读取html文件 1. Controller类一定要使用@Controller注解,不要用@RestController 2. resource目录下创建templa ...

  7. 【Angular JS】网站使用社会化评论插件,以及过程中碰到的坑

    目前正在开发自己的网站,技术上使用Angular JS + Express JS + Mongo DB.由于网站会有文章发布,因此需要有评论功能.评论功能也可以自己开发,但由于现在社会化评论插件很多, ...

  8. 今天碰到的angular 中的一个小坑

    最近在自个儿研究angular,在写一个demo的时候总是有问题,最后发现居然是大小写的问题,卧槽 特tm的坑爹了,代码如下: <!DOCTYPE html> <html lang= ...

  9. 运行Appium碰到的坑们

    运行Appium的时候,碰到的那些坑 1. java命令会出现error:could not open ...jvm.cfg 出现这种情况大多是因为电脑上之前安装过JDK,卸载重装之后,运行java命 ...

随机推荐

  1. HBase运维实践-聊聊RIT的那点事

    相信长时间运维HBase集群的童鞋肯定都会对RIT(Region-In-Transition,很多参考资料误解为Region-In-Transaction,需要注意)有一种咬牙切齿的痛恨感,一旦Reg ...

  2. angular-cli.json配置参数解释,以及依稀常用命令的通用关键参数解释

    一. angular-cli.json常见配置 { "project": { "name": "ng-admin", //项目名称 &quo ...

  3. com.opensymphony.xwork2.util.logging.jdk.JdkLogger info 错误

    在启动Tomcat时出现了如下的错误: 警告: Could not create JarEntryRevision for [jar:file:/E:/Programming/apache-tomca ...

  4. POJ 3278 抓奶牛(BFS入门题)

    描述 农夫约翰已被告知逃亡牛的位置,并希望立即抓住她.他开始于一个点Ñ(0≤ Ñ ≤100,000)上的数线和牛是在点ķ(0≤ ķ上相同数目的线≤100,000).农夫约翰有两种交通方式:步行和传送. ...

  5. Cocos Creator学习四:按钮响应事件

    1.方法一:通过编辑器对cc.Button的属性进行拖放操作进行控制 (1)创建脚本BtnClick1.js,增加btnClick1函数,然后拖放到Canvas节点中(记得拖放,否则下面步骤将找不到对 ...

  6. Python3编译安装以及创建虚拟运行环境

    一.yum安装pip# yum -y install epel-release   #Centos6.8安装epel源# yum -y install python-pip手动安装pip# wget ...

  7. linux存储管理之基本分区

    基本分区管理 ====================================================================================基本分区(MBR| ...

  8. nlp基础(一)基本应用

    1.问答系统,它主要是针对那些有明确答案的用户问题,而且通常面向特定的领域,比如金融,医疗,这一类的机器人.它的技术实现方案分为基于检索和基于知识库两大类. 2.第二个任务型对话系统,大家看论文的时候 ...

  9. doctrine/annotation 的简单使用

    <?php // 错误处理机制 register_shutdown_function('myShutDown'); set_error_handler('myError'); set_excep ...

  10. windows10安装MongoDB服务启动不了 😀✅已解决!

    WIndows的服务中,有一个服务需要以NT  AUTHORITY\NetworkService用户启动,但怎么也启动不起来,使用本地系统帐户启动没有任何问题,但是换成NetworkService就启 ...