[关闭]
@masquevil 2015-12-14T05:17:27.000000Z 字数 982 阅读 74

Angular.js 的 onRenderFinish

Angular.js 前端开发 js


Angular.js在使用的过程中,经常会有这样的需求:在ng-repeat结束后,执行某段JS。

一开始我是这么做的:

  1. IMCtrls.directive('onRenderFinish', function($timeout){
  2. return {
  3. restrict:'A',
  4. link: function($sc, element, attrs, controller){
  5. if($sc.$last === true || $sc.$last === undefined)$sc.$eval(attrs.onRenderFinish);
  6. }
  7. };
  8. });

判断 ng-repeat 到最后一个元素的时候($last 为 true),或者不在 ng-repeat 的元素上使用 onRenderFinish 的时候($last 为 undefined),执行 onRenderFinish 内的方法。

后来在使用的过程中,发现一个坑:
当使用 concat 构建 ng-repeat 元素的时候,angular 会出于性能优化的原因,不会重复渲染已经渲染过的元素。
比如下面的代码:

  1. <!-- …… -->
  2. <a ng-repeat="a in as" on-render-finish="fun()">{{ a.a }}</a>
  3. <!-- …… -->
  4. <script>
  5. // ……
  6. $scope.fun = function(){alert(1);};
  7. // ……
  8. b = [{a:1}];
  9. $scope.as = b.concat($scope.as);
  10. // ……
  11. </script>

只有 b 中的元素会被重新渲染,也就是只有 b 中的元素会去查看他的 onRenderFinish。
很明显,b 中的元素 $last 恒不为 true,所以无法正确的触发 ng-repeat 结束后的 js。

经过研究,我改成了这样:

  1. IMCtrls.directive('onRenderFinish', function($timeout){
  2. return {
  3. restrict:'A',
  4. link: function($sc, element, attrs, controller){
  5. $timeout(function(){if(!$sc.$$nextSibling)$sc.$eval(attrs.onRenderFinish);});
  6. }
  7. };
  8. });

目前已经能够满足要求。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注