本文介绍如何在AngularJS中通过自定义指令监听ng-repeat渲染完成。利用内置变量$last判断遍历结束,结合$eval执行回调函数,并支持通过事件机制通知多个控制器,实现灵活的业务逻辑处理。
前言
前言
在使用AngularJS时,经常使用ng-repeat。业务场景中,有时需要在异步获取数据并通过ng-repeat遍历渲染页面后执行特定操作。Angular本身未提供监听ng-repeat渲染完成的指令,因此需自定义实现。熟悉Angular的同学应知,在ng-repeat模板实例内部会暴露出一些特殊属性$index/$first/$middle/$last/$odd/$even,$index会随着每次遍历(从0开始)递增。当遍历到最后一项时,$last的值为true。因此,通过判断$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>
</div>
通过观察控制台输出,可以看到索引值0、1、2依次打印。当$index等于2时,$last的值变为true,表明ng-repeat已完成全部渲染。
实现过程相对简单。
指令复用与函数调用
为了提高指令的复用性,不应在指令内部硬编码具体业务逻辑。可以通过为指令指定一个处理函数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渲染完成后可能需要执行多个操作,且这些操作由不同的前端模块负责。此时可以利用AngularJS的事件机制:在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(){
//子控制器执行操作
})
若需在当前控制器下监听该事件,由于AngularJS未提供直接向当前控制器传递事件的方法,可采用间接方式:先向父控制器或子控制器广播事件,由父(子)控制器监听到后,再反向向子(父)控制器传递事件,从而实现跨层级通信。
IE8兼容方案
补充说明:在IE8浏览器中,可以直接在元素上使用指令ng-if="$last && renderFinish()"来实现相同功能,该方法同样适用于IE8及以上版本。
总结
总结
以上介绍了利用AngularJS指令监听ng-repeat渲染完成并执行脚本的完整流程。希望本文内容能对各位的学习或工作有所帮助,如有疑问欢迎留言交流。