677

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

一种 jQuery 监听调整大小事件的方法,但我不希望将它带入我的项目中,只是为了满足这一要求。

4

13 回答 13

708

最佳做法是附加到调整大小事件。

window.addEventListener('resize', function(event) {
    ...
}, true);

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

window.onresize = function(event) {
    ...
};

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

于 2009-03-13T08:58:05.363 回答
613

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

window.addEventListener('resize', function(event){
  // do stuff here
});

这是一个工作示例

于 2013-08-29T20:32:33.057 回答
535

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

相反,创建一个函数以将事件侦听器添加到对象或元素。这会检查并以防监听器不起作用,然后它会覆盖对象的功能作为最后的手段。这是 jQuery 等库中使用的首选方法。

object:元素或窗口对象
type:调整大小、滚动(事件类型)
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;
    }
};

然后使用是这样的:

addEvent(window, "resize", function_reference);

或使用匿名函数:

addEvent(window, "resize", function(event) {
  console.log('resized');
});
于 2010-06-30T14:19:45.970 回答
45

永远不要直接使用 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);
    };
};

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

window.addEventListener('resize', debounce(() => console.log('hello'),
200, false), false);

它不会每 200 毫秒触发一次以上。

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

window.addEventListener('orientationchange', () => console.log('hello'), false);

这是我整理的一个小图书馆,可以很好地处理这个问题。

于 2017-04-06T03:12:56.840 回答
43

2018+ 解决方案:

您应该使用ResizeObserverresize它是一种浏览器原生解决方案,其性能比使用事件要好得多。此外,它不仅支持上的事件,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);

目前,Firefox、Chrome、Safari 和 Edge 都支持它。对于其他(和更旧的)浏览器,您必须使用polyfill

于 2018-03-20T10:00:27.483 回答
16

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

主要有两个问题:

  1. 切勿object用作参数名称。这是一个保留词。话虽如此,@Alex V 提供的功能在strict mode.

  2. @Alex V 提供的addEvent函数不返回event objectif 该addEventListener方法是否被使用。另一个参数应该添加到addEvent函数中以允许这样做。

注意:新参数 toaddEvent已设为可选,因此迁移到此新函数版本不会中断对该函数的任何先前调用。将支持所有遗留用途。

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;
};

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);
于 2015-10-05T18:38:42.377 回答
11

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

虽然您可以连接到标准的窗口调整大小事件,但您会发现在 IE 中,每个 X 轴和每个 Y 轴移动都会触发一次该事件,从而导致触发大量事件,这些事件可能具有性能如果渲染是一项密集的任务,则会对您的网站产生影响。

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

于 2009-12-05T18:50:43.967 回答
7
window.onresize = function() {
    // your code
};
于 2009-11-16T05:27:55.777 回答
5

以下博客文章可能对您有用:修复 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);
}
于 2009-03-13T09:00:25.313 回答
3

如果您只想调整窗口和窗口的大小,上面已经提到的解决方案将起作用。但是,如果您想将调整大小传播到子元素,则需要自己传播事件。这是一些示例代码:

window.addEventListener("resize", function () {
  var recResizeElement = function (root) {
    Array.prototype.forEach.call(root.childNodes, function (el) {

      var resizeEvent = document.createEvent("HTMLEvents");
      resizeEvent.initEvent("resize", false, true);
      var propagate = el.dispatchEvent(resizeEvent);

      if (propagate)
        recResizeElement(el);
    });
  };
  recResizeElement(document.body);
});

请注意,子元素可以调用

 event.preventDefault();

在作为调整大小事件的第一个 Arg 传入的事件对象上。例如:

var child1 = document.getElementById("child1");
child1.addEventListener("resize", function (event) {
  ...
  event.preventDefault();
});
于 2014-04-20T03:55:19.340 回答
1
<script language="javascript">
    window.onresize = function() {
    document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
} 

</script>
于 2011-04-13T20:30:10.903 回答
1
var EM = new events_managment();

EM.addEvent(window, 'resize', function(win,doc, event_){
    console.log('resized');
    //EM.removeEvent(win,doc, event_);
});

function events_managment(){
    this.events = {};
    this.addEvent = function(node, event_, func){
        if(node.addEventListener){
            if(event_ in this.events){
                node.addEventListener(event_, function(){
                    func(node, event_);
                    this.events[event_](win_doc, event_);
                }, true);
            }else{
                node.addEventListener(event_, function(){
                    func(node, event_);
                }, true);
            }
            this.events[event_] = func;
        }else if(node.attachEvent){

            var ie_event = 'on' + event_;
            if(ie_event in this.events){
                node.attachEvent(ie_event, function(){
                    func(node, ie_event);
                    this.events[ie_event]();
                });
            }else{
                node.attachEvent(ie_event, function(){
                    func(node, ie_event);
                });
            }
            this.events[ie_event] = func;
        }
    }
    this.removeEvent = function(node, event_){
        if(node.removeEventListener){
            node.removeEventListener(event_, this.events[event_], true);
            this.events[event_] = null;
            delete this.events[event_];
        }else if(node.detachEvent){
            node.detachEvent(event_, this.events[event_]);
            this.events[event_] = null;
            delete this.events[event_];
        }
    }
}
于 2015-09-01T18:18:00.973 回答
0

您可以使用以下适用于小型项目的方法

<body onresize="yourHandler(event)">

function yourHandler(e) {
  console.log('Resized:', e.target.innerWidth)
}
<body onresize="yourHandler(event)">
  Content... (resize browser to see)
</body>

于 2020-09-07T20:10:36.467 回答