窗口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事件的主要内容,如果未能解决你的问题,请参考以下文章