AngularJS观看DOM变化

时间:2014-01-24 12:24:40

标签: angularjs dom angularjs-directive angular-ng-if

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

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

如何确保父指令知道它的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,但这不会回答问题而不是我需要的问题。

5 个答案:

答案 0 :(得分: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-repeatng-ifng-switchng-include等指令使用注释占位符来执行转换并更改DOM,而children仅保留元件。

答案 1 :(得分:18)

如果您需要观察元素主题中更深层次的变化,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
            });
        }
    };
});

答案 2 :(得分: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-createdom-on-destroy,但其性能优于接受的答案,因为它只会针对每个dom事件触发一次,而不是反复检查$ watch回调。

答案 3 :(得分:1)

虽然我认为没有使用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>

答案 4 :(得分: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
        }
    }
}]);