angularjs执行ng-repeat判断完成状态,生成可复用性自定义指令

更新
问题背景

今天整体把页面js重写过了下,发现了新的问题。

ng-repeat如做了ng-if判断做过滤显示,那渲染完后就拿不到scope.$last为true的情况,此时使用下面on-finish-render方法在调用则不会触发。

测试后发现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,则能正常使用,如下图。
在这里插入图片描述
这里猜测是:

  1. 一是scope.$last获取的是队列里的最后一个元素下标状态;(正确
  2. 二是必须全部所有元素被数据填充完才能获取到的状态。(正确

猜测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.controller()内定义事件监听

//attr.onFinishRender可以让onFinishRender指令重复使用
$scope.$on('afterRightEditRepeat', function(event){
	console.log('右边菜单内容填充完成');		
})

//只需要在给属性赋值时根据后续逻辑匹配不同的监听事件即可
$scope.$on('afterTopMenuRepeat', function(event){
	console.log('左边顶级菜单加载完成');
})
解释

原先是想直接在angular controller内部使用jquery获取ng-repeat的元素,结果拿到了undefined,然后又使用angul.elment获取元素,报错
在这里插入图片描述
原因是jquery应优先加载
在这里插入图片描述
正确加载顺序如图
在这里插入图片描述
但结果仍是undefined。

继续探索…

做了两种考虑,都是关于页面加载的

一是先想到的可能是window.onload,$(document).ready(function(){})的问题。

代码包裹在window.onload里后,页面刷新提示了控制器app.controller(aa())未加载的错误如下。
在这里插入图片描述
尝试简化写法app.controller()也是直接报错,说明不是代码以及调用顺序问题。而觉得app.controller()在window.onload里面这种写法也许就是存在错误的。

想想其实很合理,元素要被渲染后后才能实现DOM树完全加载(执行$.ready()),编译阶段需要控制器提供数据的,app.controller最好直接写在页面(scripts加载)里面。

二是考虑到渲染的问题,用alert()走了一下页面,发现好几个地方的alert()弹出来的时候页面还是空白,说明数据都没加载出来,元素自然也没有出来,所以拿了个空。
在这里插入图片描述
于是去搜元素渲染的相关解决办法,百度还算顺利。

获取了两个知识

scope.$last 表示渲染完的状态,是最后一条则为true
scope.$emit() 表示触发事件

就是记住在自定义指令写成元素属性后进行赋值的时候,值不要写成事件调用的形式,要是个字符串,scope.$emit()才能调用成功。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值