Angular 指令在路由更改后不起作用

Angular directive not working after route change

作为 Angular 的新手,我目前正在使用 angular 和 Angular Material 构建一个应用程序,试图编写我的第一个指令,我 运行 遇到了一些麻烦。

我想做的事:在页面上放一张卡片,卡片顶部有一个工具栏。一旦工具栏滚动到屏幕顶部,它就会 "stick" 在那里。为了完成这个行为,我写了一个简单的指令。

app.directive("sticky", function() {

return {
  restrict: 'A',
  link: function(scope, element, attrs) {

      //"content" is the container in which my app scrolls.
      var content = document.getElementById('content');
      angular.element(content).bind("scroll", function() {

        var cardOffset = element[0].parentElement.offsetTop;
        var scrolled = content.scrollTop;
        var cardHeight = element[0].parentElement.clientHeight;
        var bottomOffset = cardOffset + cardHeight;

        //Check if we are currently scrolling through this element.
        if (scrolled >= cardOffset && scrolled <= bottomOffset) {
          element[0].style.top = (scrolled - cardOffset) + 'px';
          scope.shadow = true;
        } else {
          scope.shadow = false;
        }
        if (scrolled <= cardOffset) {
          element[0].style.top = '0px';
        }

      });
  }
}

});

这是一个plunker of that in action。您可能会注意到 plunker 的工作方式与我上面描述的一样。

然而,当我将它放入我的应用程序时,我得到以下奇怪的行为:当访问包含粘性元素的视图时,所述元素没有粘性行为。 我最初的猜测是 $routeProvider 有问题,但正如 plunker 所说明的那样,它可以解决这个问题。

我真的迷路了,正在寻找我可以研究的想法来解决我的问题。

这类问题的发生通常是因为DOM在JS运行之前还没有完全加载。如果您在元素周围添加 $timeout 则它可以正常工作。

查看编辑过的插件:https://plnkr.co/edit/xyjNRuEpRQ09KFHFcHjx?p=preview

app.directive("sticky", ['$timeout', function($timeout) {

  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      $timeout(function() {
        var content = document.getElementById('content');
        angular.element(content).bind("scroll", function() {

          var cardOffset = element[0].parentElement.offsetTop;
          var scrolled = content.scrollTop;
          console.log(scrolled);
          var cardHeight = element[0].parentElement.clientHeight;
          var bottomOffset = cardOffset + cardHeight;

          //Check if we are currently scrolling through this element.
          if (scrolled >= cardOffset && scrolled <= bottomOffset) {
            element[0].style.top = (scrolled - cardOffset) + 'px';
            scope.shadow = true;
          } else {
            scope.shadow = false;
          }
          if (scrolled <= cardOffset) {
            element[0].style.top = '0px';
          }

        });
      }, 0);
    }
  }
}]);