AngularJS指令中监听窗口大小变化

51

我有一个揭示模块模式,看起来像这样:

'use strict';

angular.module('app', [])
   .directive('myDirective', ['SomeDep', function (SomeDep) {
       var linker = function (scope, element, attr) {
          // some work
       };

       return {
          link: linker,
          restrict: 'E'
       };
   }])
;

我遇到的困难是将 $watch 整合到这个项目中,特别是使用 '$window' 服务检测窗口的调整大小。

[编辑]:

我意识到我一直以来的问题……我限制了元素,却忘记了我是将其作为属性实现的……@_@;


如果您找到了下面未提供的解决方案,请提供并接受答案,以便解决此帖子。不要在问题本身中回答问题。 - isherwood
3个回答

94

你不需要使用 $watch 。只需将窗口的 resize 事件绑定到相应的元素上即可:

DEMO

'use strict';

var app = angular.module('plunker', []);

app.directive('myDirective', ['$window', function ($window) {

     return {
        link: link,
        restrict: 'E',
        template: '<div>window size: {{width}}px</div>'
     };

     function link(scope, element, attrs){

       scope.width = $window.innerWidth;

       angular.element($window).bind('resize', function(){

         scope.width = $window.innerWidth;

         // manuall $digest required as resize event
         // is outside of angular
         scope.$digest();
       });

     }

 }]);

12
如果该指令不再在页面上使用怎么办?那么每个曾经存在过该指令的元素都将毫无意义地触发事件回调,而且会持续不断地触发,无论当前显示哪个模板,访问带有该指令的页面100次,事件都会被处理100次。 - user3338098
8
如果您想在指令未使用时进行清理工作,请在指令上实现 $destroy。 - David Salamon
您的简洁易懂非常受欢迎。 - R Claven

41

您可以监听resize事件,并在某些尺寸发生变化时触发。

指令

(function() {
'use strict';

    angular
    .module('myApp.directives')
    .directive('resize', ['$window', function ($window) {
        return {
            link: link,
            restrict: 'A'
        };

        function link(scope, element, attrs){
            scope.width = $window.innerWidth;
            function onResize(){
                // uncomment for only fire when $window.innerWidth change   
                // if (scope.width !== $window.innerWidth)
                {
                    scope.width = $window.innerWidth;
                    scope.$digest();
                }
            };

            function cleanUp() {
                angular.element($window).off('resize', onResize);
            }

            angular.element($window).on('resize', onResize);
            scope.$on('$destroy', cleanUp);
        }
    }]);
})();
在HTML中
<div class="row" resize> ,
    <div class="col-sm-2 col-xs-6" ng-repeat="v in tag.vod"> 
        <h4 ng-bind="::v.known_as"></h4>
    </div> 
</div> 

控制器:

$scope.$watch('width', function(old, newv){
     console.log(old, newv);
 })

3
这段代码缺少 unbind 的调用,很可能会创建僵尸监听器,例如在应用内导航到不同的视图时。 - dube

1
// 以下是Angular 2.0的指令,用于调整给定元素的滚动条以适应您的标记。
---- angular 2.0 window resize directive.
import { Directive, ElementRef} from 'angular2/core';

@Directive({
       selector: '[resize]',
       host: { '(window:resize)': 'onResize()' } // Window resize listener
})

export class AutoResize {

element: ElementRef; // Element that associated to attribute.
$window: any;
       constructor(_element: ElementRef) {

         this.element = _element;
         // Get instance of DOM window.
         this.$window = angular.element(window);

         this.onResize();

    }

    // Adjust height of element.
    onResize() {
         $(this.element.nativeElement).css('height', (this.$window.height() - 163) + 'px');
   }
}

1
提问者明确标记了 AngularJS,也就是 Angular 1,不是吗? - Ivan Rubinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接