【经验】AngularJS

时间:2023-03-09 00:51:43
【经验】AngularJS

1.关于ng-model

<textarea id="feature_name" class="col-sm-3" placeholder="软件特征" ng-model="data.dlls[$index]" ng-repeat="i in data.dlls track by $index"></textarea>

注意ng-model="data.dlls[$index]",如果改成ng-model="i",虽然会成功将dlls里的内容显示在文本区中,但是当dlls.push新项时(就创建新的textarea),之前的textarea中显示的内容将消失。
2.当directive被放置到控制器中时,在directive里的ng表达式所引用的变量与直接写在控制器的html中的变量无异。
3.每一次ng事件,都会检查所有的值。ng-checked是最好的证明,如果一个input 被选中,然后去触发其他元素的ng事件,这个input上的ng-checked中绑定的事件处理函数也会被执行。
同样的,$watch监听着任何事件,只要触发了任何事件,其中的函数都会被执行(不符合逻辑)。
4.$cookies.a 返回的是一个字符串,而$cookieStore.a返回的可以是number或boolean
5.之前想要根据cookie判断信息是否显示过某段文本,文本形如

<p id="updateInfo" ng-if="updateInfo" update-info>
homeApp.controller('homeMainCtrl', ['$scope', '$timeout', '$cookieStore', function($scope, $timeout, $cookieStore){}]);
homeApp.directive('updateInfo',['$timeout', '$cookieStore', function($timeout, $cookieStore){
return {
priority:599,//注意这个值
link: function(scope,elem,attr){
$cookieStore.put('updateInfoShowed',false);
if($cookieStore.get('updateInfoShowed')){
scope.updateInfo = false;
}
else {
scope.updateInfo = true;
$cookieStore.put('updateInfoShowed',true);
$timeout(function(){
elem.slideToggle();
},8000);
}
console.log(document.getElementById('updateInfo'))//注意这个console
}
};
}]);

当priority:599时,根本没有执行console。
猜测:是因为ng-if的指令优先度较高,执行我这条指令时,p元素已经被ng-if指令移出出dom或者设置dispaly:none了,所以没有执行link中的代码。
例证1:把ng-if改为ng-show,console出p的dom。
例证2:当priority:600时,console结果为null,也就是说提高了优先度console就被执行了。

例证2输出null意味着在本指令的link函数执行时元素不存在dom中。而例证1说明在本指令的link函数执行时dom已经存在。
那么,例证2中元素之所以不存在,原因可能有2:
(1)是否因为ng-if?难道ng-if的优先度比600要大?
如果是这样,那么599与600间的分界是什么导致的?
(2)还是因为ng-if,而ng-if的优先度确实是599。
在这种假设下,另一种可能性是ng-if在compile期做过些什么。

6.alert会阻塞线程,所以要使用setTimeout(function(){alert()},0)
7.jQuery.ajax({url:"/a.html",type:"GET"})和jQuery.get("/a.html")有区别,前者似乎会被angularjs认为是对文件的访问,后者会被ng进行路由处理。
8.重载视图使用 $route.reload();
9.在directive里elem.on('click',function(){scope.day = 'yesterday'}),这是想改变scope的day,但会导致controller中的$scope.$watch失效,view里也不会更新(即使是在directive所在元素内)。
这种时候要写成

yesterday.on('click', function(){
scope.$apply(function(){
scope.day = 'yesterday';
})
});

10.ng-cloak闪烁问题。写.ng-hide{display:none},然后在元素中添加.ng-hide
11.template文件中的html,应该保持其独立性,比如:
<div ng-template></div>
template.html:
<ul><li></li></ul>
固然这样写也可以:
<ul ng-template></ul>
template.html:
<li></li>
但是template.html就缺乏了独立性,它被限定了必须被一个ul所包括。
12.ng-class使用{xx:xx}[data-list-row]是无效的,只能换用驼峰写法。
13.ng-if会销毁dom,重现加载时会重载dom以及指令,恐怕作用域也会重载。但是ng-if所在的元素,其template不会被重载
14.子元素$emit,父元素$broadcast给那个子元素的兄弟元素,这可以,但是要注意事件的名称不能一致。
15.$location.search()可以获取?后的键值对
16.有混合ng的src与href一定要使用ng-src和ng-href。不然,前者会在某些浏览器上导致跳转到404页面。
17.$anchorScroll会根据hash跳转,但修改hash会导致页面刷新,要这么写:

var old = $location.hash()
$location.hash(id);
$anchorScroll();
$location.hash(old)

18.ng-change会根据ng-pattern决定是否触发。要每次按键触发使用ng-press
19.ng-style="{true: {'color': 'red'}}[true]"
20.$timeout在作用域on('$destory')时一定要销毁
21.ng-bind="010203"会显示10203,可能是进制问题
22.使用ng-if在指令或者指令的父元素上时,可能会导致ng-if这个指令先于自定义指令被执行,导致自定义指令执行时找不到dom而无效。
23.我曾在指令内试图将使用了ng-model="formData.password"绑定数据的formData传给服务器,但结果formData为undefined。解决办法是在指令link里加scope.formData = {};原理未知。
24.给指令设置scope:{}可能会导致其中的子元素上的指令失效
25.ng的$resource服务若无写getGroup: {url: '/client/group/index', method: 'GET', responseType: 'arraybuffer'}这里的responseType,会默认返回的是json作处理,如果不是json会报错如:
Error: [$resource:badcfg] http://errors.angularjs.org/1.2.26/$resource/badcfg?p0=object&p1=array
25.1 其实应该写isArray: true
26.不能在$resource里刷时间戳,如:
 clientDetail: {params: {m: 'eqdetail', t: (new Date).getTime()}, method: 'GET'} 
这样会导致所有时间戳都固定为同一个数字,必须写成
 softwareService.clientDetail({uuid: client.uuid, t: (new Date).getTime()}) 
27.指令中使用replace:true时,要保证模板被包括在一个容器中,
<input /><p></p>——这样是不行的,会报错如:Error: [$compile:tplrt] Template for directive 'rewardPoint' must have exactly one root element. /js/apps/main/tpl/rewardPoint.html
<div><input /><p></p></div>——必须如此加个div包括,其实这样我何苦使用replace:true
28.ng-href="{{ down({fileType: 'csv'}) }}" ng-href中使用函数一定要在最外面用大括号括起来,其实在html里使用ng表达式写函数都得这么干
29.得注意变量命名,如果命名tab-index,在{{ tab-index }}会理解为tab 减去 index,常常结果为0。
30.若在作用域中写$scope.f = function(d){$scope.data = d;};再在其子作用域中调用scope.f('text');结果会给父作用域的$scope.data赋值。
应该改写成this.data = d;
31.ng-click会触发ng循环,所以执行的代码中不能执行$apply
32.scope.vm的最大作用是让子元素的成员改变同时能改动到父元素的成员。
33.单例模式如factory,其生命期为应用的生命期。所以是否使用factory存放vm,需要考虑。
34. $apply会使ng进入 $digest cycle , 并从$rootScope开始遍历(深度优先)检查数据变更。
$digest仅会检查该scope和它的子scope,当你确定当前操作仅影响它们时,用$digest可以稍微提升性能。
35.directive中执行的 $evalAsync , 会在angular操作DOM之后,浏览器渲染之前执行。
36.在html里的ng-click要获取this,可以使用$event.currentTarget
37.var binder = scope.$on('xxx');要解绑,执行binder()
38.$cookieStore.get(...),只能访问到path允许访问的值
39.ng-if会产生子作用域。使用这种指令时,其内部无作用域指令对scope的修改都会修改到它的作用域;如果目标作用域在ng-if之上就会出错。
解决方案一般有1.使用ng-show代替ng-if。2.使用factory注入,修改factory
40.ng发get请求,貌似会删除值为undefined的属性
41.使用track by可以免去移除dom再生成dom的步骤提高性能。
41.1 但是正因为不再生成dom,所以新生成的元素上的directive指令也不会被运行。所以能不能既利用原有dom,又渲染指令呢?
42.
$http().then(function(n)) // n是包装过的,真实数据在n.data里
$http().success(function(data)) // data就是真实数据
43. 我常常疑惑什么应该写在controller里,什么应该写到directive里。
controller会先于任何directive加载,而directive加载会有顺序,先子后父。根据这个来考虑怎么写吧。
44.当directive内有个templateUrl的子directive时,directive内使用elem.find()貌似找不到子directive的内容。
45.ng里可以在controller或factory等任何地方中通过$compile服务渲染指令。但指令不会即时被渲染,至少不会在controller中立即被渲染,而是在后续的检查中被渲染。除非你在父作用域或指令的作用域上调用了scope.$digest(),则指令将被立即渲染。
立即渲染意味着立即发起对模板的请求。