AngularJS - 绑定到指令resize

li-*_*raz 22 angularjs angularjs-directive

如何在调整指令大小时通知我?我试过了

element[0].onresize = function() {
            console.log(element[0].offsetWidth + " " + element[0].offsetHeight);
        }
Run Code Online (Sandbox Code Playgroud)

但它没有调用这个功能

(function() {
'use strict';

// Define the directive on the module.
// Inject the dependencies. 
// Point to the directive definition function.
angular.module('app').directive('nvLayout', ['$window', '$compile', layoutDirective]);

function layoutDirective($window, $compile) {
    // Usage:
    // 
    // Creates:
    // 
    var directive = {
        link: link,
        restrict: 'EA',
        scope: {
            layoutEntries: "=",
            selected: "&onSelected"
        },
        template: "<div></div>",
        controller: controller
    };
    return directive;

    function link(scope, element, attrs) {
        var elementCol = [];

        var onSelectedHandler = scope.selected();

        element.on("resize", function () {
            console.log("resized.");
        });

        $(window).on("resize",scope.sizeNotifier);

        scope.$on("$destroy", function () {
            $(window).off("resize", $scope.sizeNotifier);
        });

        scope.sizeNotifier = function() {
            alert("windows is being resized...");
        };

        scope.onselected = function(id) {
            onSelectedHandler(id);
        };



        scope.$watch(function () {
            return scope.layoutEntries.length;
        },
        function (value) {
            //layout was changed
            activateLayout(scope.layoutEntries);
        });

        function activateLayout(layoutEntries) {


            for (var i = 0; i < layoutEntries.length; i++) {

                if (elementCol[layoutEntries[i].id]) {
                    continue;
                }
                var div = "<nv-single-layout-entry id=slot" + layoutEntries[i].id + " on-selected='onselected' style=\"position:absolute;";
                div = div + "top:" + layoutEntries[i].position.top + "%;";
                div = div + "left:" + layoutEntries[i].position.left + "%;";
                div = div + "height:" + layoutEntries[i].size.height + "%;";
                div = div + "width:" + layoutEntries[i].size.width + "%;";
                div = div + "\"></nv-single-layout-entry>";

                var el = $compile(div)(scope);
                element.append(el);
                elementCol[layoutEntries[i].id] = 1;
            }


        };
    }

    function controller($scope, $element) {

    }
}

      })();
Run Code Online (Sandbox Code Playgroud)

epe*_*gzz 15

使用范围.$ watch具有自定义监视功能:

scope.$watch(
  function () {
    return [element[0].offsetWidth, element[0].offsetHeight].join('x');
  },
  function (value) {
    console.log('directive got resized:', value.split('x'));
  }
)
Run Code Online (Sandbox Code Playgroud)


Sim*_*rks 13

您通常希望观察元素offsetWidthoffsetHeight属性.使用更新版本的AngularJS,您可以$scope.$watchGroup在链接功能中使用:

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

    function link($scope, element) {
        var container = element[0];

        $scope.$watchGroup([
            function() { return container.offsetWidth; },
            function() { return container.offsetHeight; }
        ],  function(values) {
              // Handle resize event ...
        });
    }

    // Return directive definition ...

}]);
Run Code Online (Sandbox Code Playgroud)

但是,您可能会发现,以这种方式直接观察元素属性时更新速度非常慢.

为了使您的指令更具响应性,您可以通过使用来降低刷新率$interval.以下是可重复使用服务的示例,用于以可配置的毫秒速率观察元素大小:

app.factory('sizeWatcher', ['$interval', function($interval) {
    return function (element, rate) {
        var self = this;
        (self.update = function() { self.dimensions = [element.offsetWidth, element.offsetHeight]; })();
        self.monitor = $interval(self.update, rate);
        self.group = [function() { return self.dimensions[0]; }, function() { return self.dimensions[1]; }];
        self.cancel = function() { $interval.cancel(self.monitor); };
    };
}]);
Run Code Online (Sandbox Code Playgroud)

使用这种服务的指令看起来像这样:

app.directive('myDirective', ['sizeWatcher', function(sizeWatcher) {

    function link($scope, element) {
        var container = element[0],
            watcher = new sizeWatcher(container, 200);

        $scope.$watchGroup(watcher.group, function(values) {
            // Handle resize event ...
        });

        $scope.$on('$destroy', watcher.cancel);
    }

    // Return directive definition ...

}]);
Run Code Online (Sandbox Code Playgroud)

注意调用watcher.cancel()$scope.$destroy事件处理程序; 这可确保$interval在不再需要时销毁实例.

这里可以找到一个JSFiddle示例.

  • 无论谁想要使用这种方法,都要考虑用`$ interval(self.update,rate,0,false);`替换`$ interval(self.update,rate);`,它明确表示不会在最后调用$ apply.否则将在每个间隔回调函数调用上调用范围的摘要.你可以通过`$ scope来检查这个.$ watch(function(){console.log("invalidated");});` (3认同)

Eli*_*uzi 7

这里是您需要做的示例代码:

APP.directive('nvLayout', function ($window) {
  return {
    template: "<div></div>",
    restrict: 'EA',
    link: function postLink(scope, element, attrs) {

      scope.onResizeFunction = function() {
        scope.windowHeight = $window.innerHeight;
        scope.windowWidth = $window.innerWidth;

        console.log(scope.windowHeight+"-"+scope.windowWidth)
      };

      // Call to the function when the page is first loaded
      scope.onResizeFunction();

      angular.element($window).bind('resize', function() {
        scope.onResizeFunction();
        scope.$apply();
      });
    }
  };
});
Run Code Online (Sandbox Code Playgroud)

  • 如果仅调整指令的大小而不是窗口本身,这将不起作用. (15认同)