JavaScript窗口调整大小事件

Dea*_*unt 590 javascript javascript-events window-resize

如何挂钩浏览器窗口调整大小事件?

一种jQuery方式可以监听resize事件,但我不想将它带入我的项目中,只需要这个要求.

oll*_*iej 626

jQuery只是包装标准resizeDOM事件,例如.

window.onresize = function(event) {
    ...
};
Run Code Online (Sandbox Code Playgroud)

jQuery 可能会做一些工作来确保在所有浏览器中一致地触发resize事件,但我不确定是否有任何浏览器不同,但我鼓励你在Firefox,Safari和IE中进行测试.

  • `window.addEventListener('resize',function(){},true);` (220认同)
  • 使用此方法的一个潜在问题是您要覆盖事件,因此您无法将多个操作附加到事件.addEventListener/attachEvent组合是让您的javascript与可能在页面上执行的任何其他脚本一起使用的最佳方式. (217认同)
  • **ECMAScript 6**:`window.onresize =()=> {/*code*/};`或更好:`window.addEventListener('resize',()=> {/*code*/}); ` (28认同)
  • @SubOne是一个人们永远不应该做的完美例子. (15认同)
  • var onresize = window.onresize; window.onresize = function(event) { if (typeof onresize === 'function') onresize(); /** ... */ } (4认同)

Ale*_*x V 518

永远不要覆盖window.onresize函数.

而是创建一个函数来向对象或元素添加事件侦听器.这会检查并使侦听器不起作用,然后它会覆盖对象的函数作为最后的手段.这是jQuery等库中使用的首选方法.

object:元素或窗口对象
type:resize,scroll(事件类型)
callback:函数引用

var addEvent = function(object, type, callback) {
    if (object == null || typeof(object) == 'undefined') return;
    if (object.addEventListener) {
        object.addEventListener(type, callback, false);
    } else if (object.attachEvent) {
        object.attachEvent("on" + type, callback);
    } else {
        object["on"+type] = callback;
    }
};
Run Code Online (Sandbox Code Playgroud)

然后使用是这样的:

addEvent(window, "resize", function_reference);
Run Code Online (Sandbox Code Playgroud)

或者使用匿名函数:

addEvent(window, "resize", function(event) {
  console.log('resized');
});
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案.覆盖onresize只是不好的做法. (97认同)
  • 哈,所有额外的空检查是什么?试图在IE 4.5或其他什么工作? (8认同)
  • 请注意,从IE 11开始,不再支持`attachEvent`.未来的首选方式是`addEventListener`. (6认同)
  • 注意`elem == undefined`.有可能(虽然不太可能)"未定义"在本地定义为其他东西.http://stackoverflow.com/questions/8175673/jslint-complains-about-redefining-undefined (6认同)
  • 您想知道如何调用此函数来接收窗口大小调整事件?方法如下: addEvent(window, "resize", function_reference); :) (2认同)

Jon*_*dlm 514

首先,我知道addEventListener上面的评论中已经提到过该方法,但我没有看到任何代码.由于它是首选方法,因此它是:

window.addEventListener('resize', function(event){
  // do stuff here
});
Run Code Online (Sandbox Code Playgroud)

这是一个工作样本.

  • 这是最直截了当的答案. (63认同)
  • 许多人像你在这个例子中那样添加匿名事件监听器,但这不是一个很好的做法,因为这种方法使得它[不可能](https://www.w3.org/TR/DOM-Level-2-Events/ events.html#Events-Registration-interfaces)稍后删除这些侦听器.这曾经没有问题,因为网页无论如何都是短暂的,但在AJAX,RIA和SPA的这个时代,它正在变成一个.我们需要一种方法来管理事件监听器的生命周期.因此,最好将侦听器函数分解为一个单独的函数,以便以后可以使用`removeEventListener`删除它. (22认同)
  • 听起来像是最好的答案,因为你没有覆盖window.onresize事件:-) (7认同)
  • 为什么不是每个人都可以这样回答没有一丝不苟 (6认同)
  • 我认为 Stijn de Witt 和 quemeful 的回答都有道理。有时您关心删除事件侦听器,但在您不关心的情况下,像上面的示例中那样添加所有额外的代码是不必要的,并且可能会膨胀和降低可读性。在我看来,如果您没有想到需要删除侦听器的理由,那么这种方法是最好的解决方案。如有必要,您可以随时重写它。根据我的经验,这些需求只出现在特定情况下。 (2认同)

Und*_*ned 32

不应该直接使用resize事件,因为在我们调整大小时它会被连续触发.

使用去抖功能可以缓解多余的呼叫.

window.addEventListener('resize',debounce(handler, delay, immediate),false);

这是一个常见的辩论,在网络上漂浮,虽然在lodash中寻找更高级的辩护.

const debounce = (func, wait, immediate) => {
    var timeout;
    return () => {
        const context = this, args = arguments;
        const later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        const callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};
Run Code Online (Sandbox Code Playgroud)

这可以这样使用......

window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);
Run Code Online (Sandbox Code Playgroud)

它永远不会每200ms发射一次以上.

对于移动方向更改,请使用

window.addEventListener('orientationchange', () => console.log('hello'), false);
Run Code Online (Sandbox Code Playgroud)

这是一个小型图书馆,我把它整齐地放在一起照顾这个.

  • 仅供参考,因为你使用的是ES6 arrow func表示法,内部函数需要有`(... arguments)=> {...}`(或``args`以减少混淆),因为`arguments`变量是他们的范围不再可用. (4认同)
  • 很好的答案,需要解决调整大小的性能问题!去抖是一种选择,另一种是简单的节流(如果您需要“逐步”调整 UI 大小,这可能是一种选择)。有关示例,请参阅 http://bencentra.com/code/2015/02/27/optimizing-window-resize.html (2认同)

Web*_*rer 15

我相信@Alex V已经提供了正确的答案,但答案确实需要一些现代化,因为它已经超过五年了.

有两个主要问题:

  1. 切勿object用作参数名称.这是一个保留的词.有了这个说法,@ Alex V提供的功能将不起作用strict mode.

  2. addEvent@Alex V提供的功能event object如果使用该addEventListener方法则不返回.应该在addEvent函数中添加另一个参数以允许此操作.

注意:新参数to addEvent是可选的,因此迁移到此新函数版本不会破坏以前对此函数的任何调用.将支持所有旧版用途.

以下是更新后的addEvent功能:

/*
    function: addEvent

    @param: obj         (Object)(Required)

        -   The object which you wish
            to attach your event to.

    @param: type        (String)(Required)

        -   The type of event you
            wish to establish.

    @param: callback    (Function)(Required)

        -   The method you wish
            to be called by your
            event listener.

    @param: eventReturn (Boolean)(Optional)

        -   Whether you want the
            event object returned
            to your callback method.
*/
var addEvent = function(obj, type, callback, eventReturn)
{
    if(obj == null || typeof obj === 'undefined')
        return;

    if(obj.addEventListener)
        obj.addEventListener(type, callback, eventReturn ? true : false);
    else if(obj.attachEvent)
        obj.attachEvent("on" + type, callback);
    else
        obj["on" + type] = callback;
};
Run Code Online (Sandbox Code Playgroud)

调用新addEvent函数的示例:

var watch = function(evt)
{
    /*
        Older browser versions may return evt.srcElement
        Newer browser versions should return evt.currentTarget
    */
    var dimensions = {
        height: (evt.srcElement || evt.currentTarget).innerHeight,
        width: (evt.srcElement || evt.currentTarget).innerWidth
    };
};

addEvent(window, 'resize', watch, true);
Run Code Online (Sandbox Code Playgroud)


str*_*str 15

2018+解决方案:

您应该使用ResizeObserver.它将是一个浏览器本地解决方案,其性能远远优于使用该resize事件.此外,它不仅支持事件,document还支持任意elements.

var ro = new ResizeObserver( entries => {
  for (let entry of entries) {
    const cr = entry.contentRect;
    console.log('Element:', entry.target);
    console.log(`Element size: ${cr.width}px x ${cr.height}px`);
    console.log(`Element padding: ${cr.top}px ; ${cr.left}px`);
  }
});

// Observe one or multiple elements
ro.observe(someElement);
Run Code Online (Sandbox Code Playgroud)

目前,只有Chrome支持它,但其他浏览器可能会(很快).现在你必须使用polyfill.

  • 请问“性能更好”的说法有什么来源吗?(我不是反驳,只是问:))我知道 window:resize 会触发很多,但是对于一个简单的“if this then that”方法来说,它不应该减慢应用程序的速度,WDYT? (2认同)

Ste*_*ven 12

感谢您在http://mbccs.blogspot.com/2007/11/fixing-window-resize-event-in-ie.html上引用我的博客文章.

虽然您可以直接连接到标准窗口调整大小事件,但您会发现在IE中,每个X触发一次事件,每个Y轴移动触发一次,导致大量事件被触发,可能具有性能如果渲染是一项密集型任务,则会影响您的网站.

我的方法涉及在后续事件中取消的短暂超时,以便在用户完成窗口大小调整之前,事件不会冒泡到您的代码.


小智 7

window.onresize = function() {
    // your code
};
Run Code Online (Sandbox Code Playgroud)

  • 正如上面的许多评论所说,最好不要覆盖onresize函数; 而是添加一个新事件.看到Jondlm的回答. (22认同)

lak*_*raj 6

以下博客文章可能对您有用:修复IE中的窗口调整大小事件

它提供了以下代码:

Sys.Application.add_load(function(sender, args) {
    $addHandler(window, 'resize', window_resize);
});

var resizeTimeoutId;

function window_resize(e) {
     window.clearTimeout(resizeTimeoutId);
     resizeTimeoutId = window.setTimeout('doResizeCode();', 10);
}
Run Code Online (Sandbox Code Playgroud)

  • 这个仅适用于ASP.NET应用程序 (6认同)