angular+ui-router+layui的使用心得
近來,完成公司的一個專案,專案使用angular+ui-router+layui框架開發,由於剛剛接觸angularjs,因此遇到各種各樣的坑。在這裡記下印象最深的幾個坑;
一、ng-repeat
當陣列元素有至少兩個相同時,報Error: [ngRepeat:dupes];
//controller.js
$scope.items = [1,2,3,3,2,2];
<!-- html -->
<div ng-repeat="item in items">{{item}}</div>
解決的辦法:
<!-- html -->
<div ng-repeat="item in items track by $index">{{item}}</div>
二、指令中的scope
縱觀angularjs,可以說angular專案都是在指令的基礎上建立的,scope是連線控制層與view層的橋樑。根據需求,有時希望在指令中共享父域的變數,有時希望使用父域的變數,卻不受父域的影響,有時希望指令擁有自己獨立作用域。
指令中的scope的取值:
scope:Boolean Or Object
- scope的預設值為false:
<!-- html -->
<body >
<div ng-controller="parentCtrl">
<div><button ng-click="test1()">parent</button></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 '<button ng-click="test2()">child</button>'
},
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”;
三、angular專案與layui結合的痛點
專案中使用了大量layui的彈出層。開始時,每個模組只要用到彈出層,都會把彈出層的內容(html片段)在模組中寫出來,給個id,然後通過jquery取出來,這樣造成了該模組的程式碼臃腫,$scope中定義了大量的變數去展示它。
後來,把所有的彈出層用指令寫出來,通過元件之間的互動,將資料展示出來,並將彈出層的各種操作搬到指令,大大減少了模組的程式碼。
四、與WebSocket結合的痛點
專案中有這樣的場景:有一個房間列表,點選房間進入聊天室。使用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,這樣問題就解決了!