了解带范围的窗口大小调整事件。$ apply with $ watch on a function

时间:2015-03-07 03:56:28

标签: javascript angularjs

最近我找到了这个http://jsfiddle.net/jaredwilli/SfJ8c/,我能够让它发挥作用。

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

app.directive('resize', function ($window) {
    return function (scope, element) {
        var w = angular.element($window);
        scope.getWindowDimensions = function () {
            return {
                'h': w.height(),
                'w': w.width()
            };
        };
        scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
            scope.windowHeight = newValue.h;
            scope.windowWidth = newValue.w;

        }, true);

        w.bind('resize', function () {
            scope.$apply();
        });
    }
})

但问题是,我不知道它是如何运作的?为什么scope.$apply()?它的目的是什么?调整窗口大小时,为什么scope.getWindowDimensions会更新?

2 个答案:

答案 0 :(得分:3)

$watch的第一个参数可以是字符串或函数。如果您传递$scope.$watch('foo'之类的字符串,则会显示$scope.foo。如果传递一个函数,那么watch会在函数的返回值上。 Angular将在每个$ digest周期触发该函数。如果返回的值与前一个$ digest循环不同,则将触发回调函数(第二个参数)。在此代码中,scope.getWindowDimensions是传递的函数,当其返回值不同时,将触发回调。因此,每个$摘要周期,如果w.height()w.width()已更改,则会触发回调,并更新$ scope属性。最后,你有true(第三个)参数集,这使得$ watch深入观察,以便Angular将彻底检查对象,判断它是否相同,即使它是一个新对象每次。如果没有这个,Angular会做一个快速检查,看到它是一个新对象,并开始一个无限循环。

scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
  scope.windowHeight = newValue.h;
  scope.windowWidth = newValue.w;
}, true);

最后,除非触发$摘要周期,否则上述代码不会执行任何操作。以下代码将事件侦听器附加到window,以便在调整窗口大小时触发该函数。 scope.$apply()只会触发$ digest周期,以便检查scope.getWindowDimensions,并且会触发回调。

w.bind('resize', function () {
  scope.$apply();
});

尽管如此,我觉得这段代码有点尴尬。这就是我写它的方式。这种方式对我来说更有意义 - 更容易阅读,而且应该更高效。

app.directive('resize', function ($window) {
  return function (scope, element) {
    var w = angular.element($window);
    w.bind('resize', function () {
      // trigger $digest when window is resized and call `update` function
      scope.$apply(update);
    });
    update(); // initial setup
    function update() {
      var height = w.height();
      var width = w.width();
      scope.windowHeight = height;
      scope.windowWidth = width;
      scope.style = function() {
        return {
          'height': (height - 100) + 'px',
          'width': (width - 100) + 'px'
        };
      };
    }   
  }
})

Live demo here.

答案 1 :(得分:0)

首先,最好先google然后在这里问你的疑问,但无论如何,如果你没有得到任何东西,请点击摘要: -

w.bind('resize',callback) 

函数将窗口的resize事件绑定到w因此,如果窗口调整大小w.height()并且w.width()更改,那么您正在scope.$watch(scope.getWindowDimensions,callback);观察scope.getWindowDimensions中的更改,这肯定是要去的更改窗口大小,然后调用回调函数。

现在为什么我们使用scope.$apply();共振很简单w.bind超出了角度范围,因此您需要运行将由scop.$apply手动运行的摘要周期。

抱歉英语不好:-P