業務中有時須要在異步獲取數據並用ng-repeat遍歷渲染完頁面後執行某個操做,angular自己並無提供監聽ng-repeat渲染完成 的指令,因此須要本身動手寫。有經驗的同窗都應該知道,在ng-repeat模板實例內部會暴露出一些特殊屬性$index/$first /$middle/$last/$odd/$even,$index會隨着每次遍歷(從0開始)遞增,當遍歷到最後一個時,$last的值爲 true,so,經過判斷$last的值來監聽ng-repeat的執行狀態,怎麼在遍歷過程當中拿到$last的值:自定義指令前端
小實例,我只寫了最重要的部分app
//要循環的數據 $scope.data = [ { str: 'a' }, { str: 'b' }, { str: 'c' } ] //自定義指令repeatFinish app.directive('repeatFinish',function(){ return { link: function(scope,element,attr){ console.log(scope.$index) if(scope.$last == true){ console.log('ng-repeat執行完畢') } } } }) <div id="box"> <span ng-repeat="item in data" repeat-finish>{{item.str}}</span> </div>
打開控制檯,會打印出0,1,2,當$index = 2點時候,$last值爲true,ng-repeat渲染完畢 異步
so easy!函數
固然指令最好是可以複用,在這個指令內寫具體的業務邏輯不利於複用,能夠經過給指令指定一個處理函數renderFinishspa
<div id="box"> <span ng-repeat="item in data" repeat-finish="renderFinish()">{{item.str}}</span> </div>
再經過指令的attr參數獲取這個處理函數code
app.directive('repeatFinish',function(){
return {
link: function(scope,element,attr){
console.log(scope.$index)
if(scope.$last == true){
console.log('ng-repeat執行完畢')
scope.$eval( attr.repeatFinish )
}
}
}
})
//controller裏對應的處理函數
$scope.renderFinish = function(){
console.log('渲染完以後的操做')
}
attr獲取到的屬性只是一個字符串表達式,$scope.$eval方法是專門執行AngularJS表達式的,經過它處理函數得以執行,這樣,指令用在不一樣的地方,可傳遞不一樣的處理函數。blog
有些業務比較複雜,可能ng-repeat渲染完成以後,須要執行多個操做而且這多個操做有多個前端完成,須要用到angular的事件,在repeatFinish指令的link函數內觸發一個事件,各位前端同窗監聽該事件完成各自的操做事件
app.directive('repeatFinish',function(){
return {
link: function(scope,element,attr){
console.log(scope.$index)
if(scope.$last == true){
console.log('ng-repeat執行完畢')
//向父控制器傳遞事件
scope.$emit('to-parent');
//向子控制器傳遞事件
scope.$broadcast('to-child');
}
}
}
})
//父控制器中監聽事件
$scope.$on('to-parent',function(){
//父控制器執行操做
})
//子控制器中監聽事件
$scope.$on('to-child',function(){
//子控制器執行操做
})
如何在當前控制器下監聽到該事件呢?angular沒有向當前控制器傳遞事件的方法,能夠先向父(子)控制器傳遞事件,父(子)控制器監聽到事件後反過來向子(父)控制器傳遞事件。element
補充:IE8能夠直接在元素上用指令ng-if="$last && renderFinish()",固然IE8+也能夠這樣用字符串
一句話總結:指令是angular的核心功能之一,用好了事半功倍,監聽ng-repeat執行狀態僅僅是它功能的冰山一角吧