窗口innerWidth大小更改上的AngularJS事件

IT技术 javascript jquery angularjs angularjs-scope
2021-02-22 14:24:31

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

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

有什么建议?

4个回答

我们可以用 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 的事件命名空间你可以根据你的要求做不同的事情。

改进:如果您的事件处理程序需要很长时间来处理,为了避免用户可能不断调整窗口大小,导致事件处理程序运行多次的问题,我们可以考虑对功能进行节流如果您使用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));

限制和去抖动函数之间的区别

@user1431317:好的,非常感谢这个问题,我不知道为什么我认为它在 1 年多前就可以工作(可能在旧浏览器或不同的角度版本上)。但我会删除这些解决方案反正不推荐。
2021-04-23 14:24:31
您可能有其他事情触发了消化周期。
2021-04-27 14:24:31
@Jon Onstott:这是另一种选择,但我更喜欢使用 jQuery,因为它支持事件命名空间。这样做的原因是我们需要在作用域被销毁时取消注册事件处理程序,我不想意外取消注册所有事件处理程序(来自其他组件)。angular.element 不支持事件命名空间:docs.angularjs.org/api/ng/function/angular.element
2021-05-03 14:24:31
前两个代码片段不能正常工作。观察者功能仅在其他内容开始摘要循环时才会触发,因此这些示例不会单独工作:jsfiddle.net/U3pVM/25385
2021-05-04 14:24:31
请参阅使用 angular.element() 的 lin 的答案。更短更简单。
2021-05-06 14:24:31

不需要jQuery!这个简单的片段对我来说很好用。它使用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 似乎不会自动执行此操作。
2021-05-14 14:24:31

我找到了一个可能在这里有帮助的 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 循环。因此,只要您无论如何都必须绑定到“调整大小”并且它所做的只是触发 $digest,您也可以在“调整大小”侦听器中进行工作;这完全重复使用事件侦听器和 $watch 侦听器。
2021-05-02 14:24:31

如果 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