angularjs执行ng-repeat判断完成状态,生成可复用性自定义指令
更新 问题背景
今天整体把页面js重写过了下,发现了新的问题。
ng-如做了ng-if判断做过滤显示,那渲染完后就拿不到scope.$last为true的情况,此时使用下面on--方法在调用则不会触发。
测试后发现ng-if并非完全不可触发
(遍历json对象共5个元素,属性index为0的2个,为1的3个,元素的index排列为0,1,0,1,1,以下为模拟数据)
allmenu = {"aa":{"index":0},"bb":{"index":1},"cc":{"index":0},"dd":{"index":1},"ff":{"index":1}
}
最初样例代码(失败无法触发)
<ul><li ng-repeat='x in allMenu' ng-bind="x.name" ng-if="x.index==0" on-finish-render="afterTopMenuRepeat"></li><div class='clear'></div>
</ul>
上面代码因为使用了ng-if而无法触发完成状态,scope.$last!=true 。
而如不使用ng-if,则能正常使用,如下图。
这里猜测是:
一是scope.$last获取的是队列里的最后一个元素下标状态;(正确)二是必须全部所有元素被数据填充完才能获取到的状态。(正确)
猜测2很好论证,只有不设定ng-if即可自证,所以仅验证猜测1。
之前ng-if条件x.index == 0拿到了位置1,3的数据,现在设定x.index==1,将会拿到位置2,4,5(5是最后一个元素)的数据,并且成功触发完成状态。如下图,说明
解决办法
目前我的代码不需要很复杂的逻辑,所以采用了ng-show来代替ng-if,页面效果一致,scope.$last也能正常拿到。
-----------------------------------------------------------我是一条华丽又低调的更新分割线------------------------
先上代码
html
//调用监听事件afterRightEditRepeat,注意不要写成afterRightEditRepeat()调用形式
<div ng-repeat="x in menu" on-finish-render="afterRightEditRepeat">
....
</div>
js自定义指令部分
//onFinishRender对应属性on-finish-render
app.directive('onFinishRender', ['$timeout', afterNgRepeatRender]).controller();//调用下面这个方法判
function afterNgRepeatRender($timeout){return {restrict:'A',link:function(scope,ele,attr){if(scope.$last == true){ //scope.$last渲染完成后为true$timeout(function(){scope.$emit(attr.onFinishRender);//scope.$emit('函数声明名'),接收一个字符串//如果div的on-finish-render属性值写成了函数调用的形式,则$emit会调用失败},10)}}}
}
app.()内定义事件监听
//attr.onFinishRender可以让onFinishRender指令重复使用
$scope.$on('afterRightEditRepeat', function(event){console.log('右边菜单内容填充完成');
})//只需要在给属性赋值时根据后续逻辑匹配不同的监听事件即可
$scope.$on('afterTopMenuRepeat', function(event){console.log('左边顶级菜单加载完成');
})
解释
原先是想直接在 内部使用获取ng-的元素,结果拿到了,然后又使用angul.获取元素,报错
原因是应优先加载
正确加载顺序如图
但结果仍是。
继续探索…
做了两种考虑,都是关于页面加载的
一是先想到的可能是.,$().ready((){})的问题。
代码包裹在.里后,页面刷新提示了控制器app.(aa())未加载的错误如下。
尝试简化写法app.()也是直接报错,说明不是代码以及调用顺序问题。而觉得app.()在.里面这种写法也许就是存在错误的。
想想其实很合理,元素要被渲染后后才能实现DOM树完全加载(执行$.ready()),编译阶段需要控制器提供数据的,app.最好直接写在页面(加载)里面。
二是考虑到渲染的问题,用alert()走了一下页面,发现好几个地方的alert()弹出来的时候页面还是空白,说明数据都没加载出来,元素自然也没有出来,所以拿了个空。
于是去搜元素渲染的相关解决办法,百度还算顺利。
获取了两个知识
scope.$last 表示渲染完的状态,是最后一条则为true
scope.$emit() 表示触发事件
就是记住在自定义指令写成元素属性后进行赋值的时候,值不要写成事件调用的形式,要是个字符串,scope.$emit()才能调用成功。