简体   繁体   English

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

[英]Understanding window resize event with scope.$apply with $watch on a function

Recently I found this http://jsfiddle.net/jaredwilli/SfJ8c/ and I am able to get it works. 最近我发现了这个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();
        });
    }
})

But the problem is, I don't know how it works? 但问题是,我不知道它是如何工作的? Why scope.$apply() ? 为什么是scope.$apply() What is the purpose of it? 它的目的是什么? Why scope.getWindowDimensions will get updated when window is resized? 为什么在调整窗口大小时scope.getWindowDimensions会更新?

The first argument to $watch can be a string or a function. $watch的第一个参数可以是字符串或函数。 If you pass a string like $scope.$watch('foo' , it is watching $scope.foo . If you pass a function, then the watch is on the return value of the function. Angular will fire the function on every $digest cycle. If the returned value is different than the previous $digest cycle, the callback function (second parameter) will fire. In this code, scope.getWindowDimensions is a function being passed and when its return value is different, the callback will fire. So, every $digest cycle, if w.height() or w.width() have changed, the callback is fired, and the $scope properties are updated. Finally, you have the true (third) parameter set, which makes the $watch a deep watch, so that Angular will thoroughly check the object, to tell whether it is identical, even though it's a new object every time. Without this, Angular will do a quick check, see that it's a new object, and start an infinite loop. 如果你传递一个像$scope.$watch('foo'这样的字符串$scope.$watch('foo' ,它正在观察$scope.foo 。如果你传递一个函数,那么watch就在函数的返回值上$scope.foo将在每个$上触发函数摘要循环。如果返回的值不同于前一个$ digest循环,则会触发回调函数(第二个参数)。在此代码中, scope.getWindowDimensions是一个传递的函数,当它的返回值不同时,回调将触发那么,每个$摘要周期,如果w.height()w.width()发生了变化,则会触发回调,并更新$ scope属性。最后,你有true (第三个)参数集,这使得$观看深度观察,以便Angular将彻底检查对象,判断它是否相同,即使它每次都是一个新对象。如果没有这个,Angular会快速检查,看到它是一个新对象,并且开始无限循环。

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

Lastly, the code above won't do anything unless a $digest cycle is triggered. 最后,除非触发$摘要周期,否则上述代码将不会执行任何操作。 The following code attaches an event listener to window so that the function is fired when the window is resized. 以下代码将事件侦听器附加到window以便在调整窗口大小时触发该函数。 scope.$apply() just triggers a $digest cycle so that scope.getWindowDimensions will be checked, and the callback will be fired. scope.$apply()只触发$ digest循环,以便检查scope.getWindowDimensions ,并触发回调。

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

With all that said, I find this code to be a bit awkward. 尽管如此,我发现这段代码有点尴尬。 This is how I'd write it. 这就是我写它的方式。 This way makes a lot more sense to me - easier to read, and should be more performant. 这种方式对我来说更有意义 - 更容易阅读,并且应该更高效。

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. 现场演示。

First of all its better to google first and then ask your doubt here but anyways if you didn't get anything from it here is the summary:- 首先它最好先谷歌,然后在这里问你的疑问,但无论如何,如果你没有得到任何东西,这里是摘要: -

w.bind('resize',callback) 

function binds the resize event of window to w therefore if window resize value of w.height() and w.width() change So you are having scope.$watch(scope.getWindowDimensions,callback); 函数将窗口的resize事件绑定到w因此如果w.height()w.width()窗口调整大小值改变那么你有scope.$watch(scope.getWindowDimensions,callback); watch the changes in scope.getWindowDimensions which is definately gonna change on changing the window size which in turn calll the callback function. 观察scope.getWindowDimensions的变化,它肯定会在改变窗口大小时改变,而窗口大小又会调用回调函数。

Now why we are using scope.$apply(); 现在我们为什么要使用scope.$apply(); The reson is simple w.bind is out of scope of angular so you need to run the digest cycle which is going to run manually by scop.$apply . 共振很简单w.bind超出了角度范围,因此您需要运行将通过scop.$apply手动运行的摘要循环scop.$apply

Sorry for bad english :-P 抱歉英语不好:-P

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM