35

我有一个auto-carousel指令遍历链接元素的children

然而,孩子们还没有加载到 DOM 中,因为他们ng-if的 s 表达式还没有被解析。

如何确保父指令知道它的 DOM 树发生了变化?

        <ul class="unstyled" auto-carousel>
          <li class="slide" ng-if="name">{{name}}</li>
          ...
          <li class="slide" ng-if="email">{{email}}</li>
        </ul>

我可以使用$timeout,但感觉不可靠。我也可以使用ng-show代替,ng-if但这不能回答问题,也不是我需要的。

4

5 回答 5

74

所以这就是我最终做的事情:

我发现你可以将一个函数传递给$scope.$watch. 从那里,返回要监视更改的表达式的值非常简单。它的工作方式与为作用域上的属性传递键字符串完全一样。

link: function ($scope, $el, $attrs) {
  $scope.$watch(
    function () { return $el[0].childNodes.length; },
    function (newValue, oldValue) {
      if (newValue !== oldValue) {
        // code goes here
      }
    }
  );
}

我在看childNodes,不是children,因为childNodes列表包含元素以及文本节点和评论。这是无价的,因为 Angular 使用注释占位符来表示指令,例如,ng-repeat和执行转入和更改 DOM,而只保存元素。ng-ifng-switchng-includechildren

于 2014-01-26T08:40:58.197 回答
18

如果您需要观察元素 dom 中更深层次的任何变化,MutationObserver 是您的最佳选择:

.directive('myDirective', function() {
    return {
        ...
        link: function(scope, element, attrs) {
            var observer = new MutationObserver(function(mutations) {
                // your code here ...
            });
            observer.observe(element[0], {
                childList: true,
                subtree: true
            });
        }
    };
});
于 2015-08-10T19:56:00.380 回答
5

我为此angular-dom-events创建了一个指令模块

在你的情况下,你可以

    <ul class="unstyled" auto-carousel>
      <li class="slide" ng-if="name" dom-on-create="nameCreated()">{{name}}</li>
      <li class="slide" ng-if="email" dom-on-destroy="emailDestroyed()">{{email}}</li>
    </ul>

目前只支持dom-on-createand dom-on-destroy,但性能比接受的答案更好,因为它只会为每个 dom 事件触发一次,而不是重复检查 $watch 回调。

于 2014-08-25T22:00:36.440 回答
2

尽管我认为这与 angular 的建议不同,但您可以使用 ng-init 来触发元素的初始化:

<ul class="unstyled" auto-carousel>
    <li class="slide" ng-if="name" ng-init="recheck()">{{name}}</li>
    <li class="slide" ng-if="email" ng-init="recheck()">{{email}}</li>
</ul>
于 2015-07-14T10:21:22.983 回答
0

您可以尝试首先在链接函数中编译指令内容。例如:

angular.module('myApp').directive('autoCarousel', ['$compile', function ($compile) {

    return {
        templateUrl: 'views/auto-carousel.html',
        restrict: 'A',
        replace: true,
        link: function (scope, element, attr) {
            $compile(element.contents())(scope);

            // your code goes here
        }
    }
}]);
于 2014-01-24T13:12:19.187 回答