1. 程式人生 > >利用angular指令監聽ng-repeat渲染完成後執行指令碼

利用angular指令監聽ng-repeat渲染完成後執行指令碼

業務中有時需要在非同步獲取資料並用ng-repeat遍歷渲染完頁面後執行某個操作,angular本身並沒有提供監聽ng-repeat渲染完成的指令,所以需要自己動手寫。有經驗的同學都應該知道,在ng-repeat模板例項內部會暴露出一些特殊屬性$index/$first/$middle/$last/$odd/$even,$index會隨著每次遍歷(從0開始)遞增,當遍歷到最後一個時,$last的值為true,so,通過判斷$last的值來監聽ng-repeat的執行狀態,怎麼在遍歷過程中拿到$last的值:自定義指令

小例項,我只寫了最重要的部分

複製程式碼
//要迴圈的資料
$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> //小駝峰,repeatFinish ,用 - 隔開,repeat-finish </div>
複製程式碼

開啟控制檯,會打印出0,1,2,當$index = 2點時候,$last值為true,ng-repeat渲染完畢 

so easy!

當然指令最好是能夠複用,在這個指令內寫具體的業務邏輯不利於複用,可以通過給指令指定一個處理函式renderFinish

<div id="box">
    <span ng-repeat="item in data" repeat-finish="renderFinish()">{{item.str}}</span>
</div>

再通過指令的attr引數獲取這個處理函式

複製程式碼
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表示式的,通過它處理函式得以執行,這樣,指令用在不同的地方,可傳遞不同的處理函式。

有些業務比較複雜,可能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沒有向當前控制器傳遞事件的方法,可以先向父(子)控制器傳遞事件,父(子)控制器監聽到事件後反過來向子(父)控制器傳遞事件。

補充:IE8可以直接在元素上用指令ng-if="$last && renderFinish()",當然IE8+也可以這樣用

一句話總結:指令是angular的核心功能之一,用好了事半功倍,監聽ng-repeat執行狀態僅僅是它功能的冰山一角吧