近来,完成公司的一个项目,项目使用angular+ui-router+layui框架开发,由于刚刚接触angularjs,因此遇到各种各样的坑。在这里记下印象最深的几个坑;
当数组元素有至少两个相同时,报Error: [ngRepeat:dupes];
//controller.js
$scope.items = [1,2,3,3,2,2];
<div ng-repeat="item in items">{{item}}div>
解决的办法:
<div ng-repeat="item in items track by $index">{{item}}div>
纵观angularjs,可以说angular项目都是在指令的基础上建立的,scope是连接控制层与view层的桥梁。根据需求,有时希望在指令中共享父域的变量,有时希望使用父域的变量,却不受父域的影响,有时希望指令拥有自己独立作用域。
指令中的scope的取值:
scope:Boolean Or Object
<body>
<div ng-controller="parentCtrl">
<div><button ng-click="test1()">parentbutton>div>
<div ng-test="true">div>
div>
body>
//js
var app = angular.module('app',[]);
app.controller('parentCtrl',function($scope){
$scope.parentName = "parent";
$scope.test1=function(){
alert($scope.childName);
}
});
app.directive('ngTest',function(){
return {
restrict:'AE',
scope:false,
template:function(){
return ''
},
controller:['$scope',function($scope){
$scope.childName = "child";
$scope.test2 = function(){
alert($scope.parentName);
}
}]
}
});
点击parent按钮弹出“child”,点击child按钮弹出“parent”;
2. 将scope设置为true:
点击parent按钮弹出“undefined”,点击child按钮弹出“parent”;
3. 将scope设置为{}:
点击parent按钮弹出“undefined”,点击child按钮弹出“undefined”;
项目中使用了大量layui的弹出层。开始时,每个模块只要用到弹出层,都会把弹出层的内容(html片段)在模块中写出来,给个id,然后通过jquery取出来,这样造成了该模块的代码臃肿,$scope中定义了大量的变量去展示它。
后来,把所有的弹出层用指令写出来,通过组件之间的交互,将数据展示出来,并将弹出层的各种操作搬到指令,大大减少了模块的代码。
项目中有这样的场景:有一个房间列表,点击房间进入聊天室。使用ui-router配置如下:
var app = angular.module('app', ['ui-router',...]);
app.config(['$stateProvider','$urlRouterProvider',function($stateProvider,$urlRouterProvider){
...code
$stateProvider.state('room',{
...code
}).state('chat',{
url : '/chat',
...codde
})
}])
在聊天室的controller中用websocket去接受聊天消息,并接受服务器端推送过来的消息。在测试中发现:
同一个浏览器中,在同一个窗口打开,没有任何问题;但是多个窗口打开,如窗口A从房间a进入聊天室,然后窗口B从房间b进入聊天室。当窗口A刷新时,页面变成房间b的聊天室。那么问题来了,窗口A中的scope的变量是怎么变成了窗口B的呢?
大致分析了一下:由于窗口A和窗口B的地址是相同的,服务器推送消息时,无法区分。因此两个窗口都接受到推送过来的消息,都改变scope中的变量。当窗口刷新时,窗口A进行脏检查,于是更新接受到消息。
解决办法:
...code
state('detail',{
url : '/chat/:id',
...codde
})
传入房间id,这样问题就解决了!