原创:Angular新手容易碰到的坑,随时更新,欢迎订阅 - 雪狼·IT
在Angular群里回答新手问题一段时间了,有一些Angular方面的坑留在这里备查,希望能对各位有所帮助。这个文章将来会随时更新,不会单独开新章,欢迎各位订阅。
Q1. <div ng-include="views/user/show.html"></div> 错在哪里?
A1. 如果你这么写过,会发现这个位置啥也没有加载出来,那么,错在哪里呢?错在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. 我的指令怎么无效?
A1. 如果你排除了代码错误等问题,那么最可能得原因是restrict。restrict参数是用来规定你可以通过哪种方式来使用指令,而这个问题之所以容易成为坑,是因为restrict的默认值是A,也就是说,默认情况下,指令只能通过属性的形式使用,比如我写了一个指令叫做appHeader,那么默认情况下我只能用这样的形式使用它:<div app-header></div>,而<app-header></app-header>的形式则是无效的。
所以,如果你用返回函数的形式使用指令,那么你就只能使用属性的方式调用它,比如:
return function(scope, element, attrs) {
element.text('hello');
}
});
如果要使用元素的方式使用指令,那么你就要这样写:
return {
restrict: 'E', // 或'EA'等都可以,几种形式可以任意组合
link: function(scope, element, attrs) {
element.text('hello');
}
}
});
Q3. 修改了变量怎么界面没反应?
A3. 首先你当然要检查有没有错误以及是否确实是scope变量,如果这些都没问题,那么多半儿是$apply导致的。对于大多数操作,$apply都会自动执行,所以你不用担心,但是如果你使用了angular之外的功能,比如直接调用了setTimeout函数,挂接了jquery的事件等等,那么系统就没有机会帮你调用$apply,界面也就没有机会刷新了,但是你如果之后又做了其他会导致$apply的操作,你会发现以前“欠下”的那次界面刷新被正常执行了了 …… 迟到了的刷新仍然是bug。
典型代码如下:
$scope.time = new Date()
}, 1000);
这种情况下你在页面中绑定的time变量将不会被自动刷新,无论是通过{{}}表达式,还是通过ng-*属性或者其他任何形式。怎么改呢?这样:
$scope.$apply(function() {
$scope.time = new Date();
});
}, 1000);
不过,这不是最好的形式,最好的形式是什么呢?当然是使用angular内置的$timeout服务,它就是干这个的:
$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,那么,从这个角度查查看吧。
本文链接: 原创:Angular新手容易碰到的坑,随时更新,欢迎订阅,转载请注明。