窗口innerWidth大小更改的AngularJS事件

Posted

技术标签:

【中文标题】窗口innerWidth大小更改的AngularJS事件【英文标题】:AngularJS event on window innerWidth size change 【发布时间】:2014-03-04 18:47:09 【问题描述】:

我正在寻找一种方法来观察窗口内部宽度大小的变化。我尝试了以下方法,但没有成功:

$scope.$watch('window.innerWidth', function() 
     console.log(window.innerWidth);
);

有什么建议吗?

【问题讨论】:

【参考方案1】:

我们可以用 jQuery 做到这一点:

$(window).resize(function()
    alert(window.innerWidth);

    $scope.$apply(function()
       //do something to update current scope based on the new innerWidth and let angular update the view.
    );
);

请注意,当您在可以重新创建的范围内绑定事件处理程序(例如 ng-repeat 范围、指令范围等)时,您应该在范围被销毁时取消绑定事件处理程序.如果您不这样做,则每次重新创建范围(重新运行控制器)时,都会添加 1 个处理程序,从而导致意外行为和泄漏。

在这种情况下,您可能需要识别附加的处理程序:

  $(window).on("resize.doResize", function ()
      alert(window.innerWidth);

      $scope.$apply(function()
          //do something to update current scope based on the new innerWidth and let angular update the view.
      );
  );

  $scope.$on("$destroy",function ()
      $(window).off("resize.doResize"); //remove the handler added earlier
  );

在这个例子中,我使用了来自 jQuery 的event namespace。你可以根据你的要求做不同的事情。

改进:如果你的事件处理器处理时间有点长,为了避免用户不断调整窗口大小导致事件处理器运行多次的问题,我们可以考虑节流函数。如果你使用underscore,你可以试试:

$(window).on("resize.doResize", _.throttle(function ()
    alert(window.innerWidth);

    $scope.$apply(function()
        //do something to update current scope based on the new innerWidth and let angular update the view.
    );
,100));

去抖函数:

$(window).on("resize.doResize", _.debounce(function ()
     alert(window.innerWidth);

     $scope.$apply(function()
         //do something to update current scope based on the new innerWidth and let angular update the view.
     );
,100));

Difference Between throttling and debouncing a function

【讨论】:

前两个代码sn-ps不能正常工作。仅当其他事物启动摘要循环时才会触发观察器功能,因此这些示例将无法自行运行:jsfiddle.net/U3pVM/25385 @user1431317:好的,非常感谢这次捕获,我不知道为什么我认为它在 1 年多前就可以工作(可能在旧浏览器或不同的角度版本上)。但是如果不推荐使用这些解决方案,我将删除它们。 您可能有其他东西触发了摘要循环。 查看使用 angular.element() 的 lin 的答案。更短更简单。 @Jon Onstott:这是另一种选择,但我更喜欢使用 jQuery,因为它支持事件命名空间。这样做的原因是我们需要在作用域被销毁时取消注册事件处理程序,我不想意外地取消注册所有事件处理程序(来自其他组件)。 angular.element 不支持事件命名空间:docs.angularjs.org/api/ng/function/angular.element【参考方案2】:

不需要 jQuery! 这个简单的 sn-p 对我来说很好用。它使用angular.element() 绑定窗口大小调整事件。

/**
 * Window resize event handling
 */
angular.element($window).on('resize', function () 
    console.log($window.innerWidth);
);    

解除绑定事件

/**
 * Window resize unbind event      
 */
angular.element($window).off('resize');

【讨论】:

记得根据需要使用angular.element($window).off(...) 取消注册处理程序。当您转到不同的 Angular 页面时,Angular 似乎不会自动执行此操作。【参考方案3】:

我在这里找到了一个可能有帮助的 jfiddle:http://jsfiddle.net/jaredwilli/SfJ8c/

我已经重构了代码以使其更简单。

// In your controller
var w = angular.element($window);
$scope.$watch(
  function () 
    return $window.innerWidth;
  ,
  function (value) 
    $scope.windowWidth = value;
  ,
  true
);

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

然后您可以从 html 中引用 windowWidth

<span ng-bind="windowWidth"></span>

【讨论】:

注意,这可能只是因为有一个监听器绑定到 'resize' 事件。您不能单独使用 $watch 。 $watch 只会在某些东西导致 angular 触发 $digest 循环时运行并比较旧值和新值。窗口大小调整本身不会触发 $digest 循环。所以,只要你无论如何都必须绑定到'resize'并且它所做的只是触发一个$digest,你还不如在'resize'监听器中完成工作;这完全是重复使用事件监听器和 $watch 监听器。【参考方案4】:

如果 Khanh TO 的解决方案对您造成了 UI 问题(就像对我一样),请尝试使用 $timeout 在属性保持 500 毫秒不变之前不更新该属性。

var oldWidth = window.innerWidth;
$(window).on('resize.doResize', function () 
    var newWidth = window.innerWidth,
        updateStuffTimer;

    if (newWidth !== oldWidth) 
        $timeout.cancel(updateStuffTimer);
    

    updateStuffTimer = $timeout(function() 
         updateStuff(newWidth); // Update the attribute based on window.innerWidth
    , 500);
);

$scope.$on('$destroy',function ()
    $(window).off('resize.doResize'); // remove the handler added earlier
);

参考:https://gist.github.com/tommaitland/7579618

【讨论】:

以上是关于窗口innerWidth大小更改的AngularJS事件的主要内容,如果未能解决你的问题,请参考以下文章

JS 获取浏览器窗口大小

swf的Javascript窗口大小

用 JavaScript 控制浏览器窗口大小?

WKWebView 的调整大小处理程序中未更新 window.innerWidth/Height

JS 获取浏览器窗口大小

JS获取各种浏览器窗口大小的方法