【问题标题】:JavaScript window resize eventJavaScript 窗口大小调整事件
【发布时间】:2010-10-13 02:44:39
【问题描述】:

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

a jQuery way of listening for resize events,但我不希望仅出于这一要求将其引入我的项目中。

【问题讨论】:

  • 谢谢大家。我不关心IE,我更多的是考虑在手机上调整opera的大小。

标签: javascript window-resize


【解决方案1】:

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

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

jQuery 只是包装了标准的resize DOM 事件,例如。

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

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

【讨论】:

  • 此方法的一个潜在问题是您正在覆盖事件,因此您无法将多个操作附加到一个事件。 addEventListener/attachEvent 组合是让您的 javascript 与可能在页面上执行的任何其他脚本友好播放的最佳方式。
  • var onresize = window.onresize; window.onresize = function(event) { if (typeof onresize === 'function') onresize(); /** ... */ }
  • window.addEventListener('resize', function(){}, true);
  • @SubOne 一个完美的例子,说明一个人永远不应该这样做。
  • ECMAScript 6window.onresize = () => { /* code */ }; 或更好:window.addEventListener('resize', () => { /* code */ });
【解决方案2】:

以下博文可能对您有用:Fixing the window resize event in 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);
}

【讨论】:

  • 这个只适用于ASP.NET应用
【解决方案3】:
window.onresize = function() {
    // your code
};

【讨论】:

  • 正如上面很多cmet所说,最好不要覆盖onresize函数;而是添加一个新事件。请参阅 Jondlm 的回答。
【解决方案4】:

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

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

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

【讨论】:

  • 引用的博文已被删除 (404)。一个很好的例子,说明了为什么 SO 指南建议将内容放在这里而不是放在某个链接后面。 :(
  • 无论如何,我可以向你保证,这种技术在 12 年后已经过时了 :)
  • 对。所以现在它只是错误信息和混乱......
【解决方案5】:

永远不要覆盖 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');
});

【讨论】:

  • 这应该是公认的答案。覆盖 onresize 只是不好的做法。
  • 哈哈,所有额外的空检查是怎么回事?尝试在 IE 4.5 或其他版本中工作?
  • 您想知道如何调用此函数来接收窗口调整大小事件?方法如下: addEvent(window, "resize", function_reference); :)
  • 请注意,从 IE 11 开始,不再支持 attachEvent。未来的首选方式是addEventListener
  • 小心elem == undefined。 “未定义”可能(尽管不太可能)在本地定义为其他内容。 stackoverflow.com/questions/8175673/…
【解决方案6】:
<script language="javascript">
    window.onresize = function() {
    document.getElementById('ctl00_ContentPlaceHolder1_Accordion1').style.height = '100%';
} 

</script>

【讨论】:

    【解决方案7】:

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

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

    Here's a working sample.

    【讨论】:

    • 这是最直接的答案。
    • 听起来是最好的答案,因为您没有覆盖 window.onresize 事件:-)
    • 很多人像你在这个例子中那样添加匿名事件监听器,但这并不是一个很好的做法,因为这种方法使得impossible 稍后删除这些监听器。这在过去没有问题,因为无论如何网页都是短暂的,但在当今 AJAX、RIA 和 SPA 的时代,它正在成为一体。我们需要一种管理事件监听器生命周期的方法。因此,最好将侦听器函数分解为一个单独的函数,以便以后可以使用removeEventListener 将其删除。
    • 为什么每个人都不能这样回答,没有所有的绒毛
    • 我认为 Stijn de Witt 和 quemeful 的回答都是正确的。有时您关心删除事件侦听器,但在您不关心的情况下,添加上面示例中的所有额外代码是不必要的,并且会导致臃肿和可读性降低。在我看来,如果您没有想到需要删除侦听器的理由,那么这种方法是最好的解决方案。如有必要,您可以随时重写它。根据我的经验,这些需求只在特定情况下出现。
    【解决方案8】:

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

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

    【讨论】:

      【解决方案9】:
      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_];
              }
          }
      }
      

      【讨论】:

        【解决方案10】:

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

        主要有两个问题:

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

        2. 如果使用addEventListener 方法,@Alex V 提供的addEvent 函数不会返回event object。应在addEvent 函数中添加另一个参数以实现此目的。

        注意: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;
        };
        

        对新 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);
        

        【讨论】:

        • 我认为 attachEvent 在 2017 年不再相关。
        • @VladNicula 我同意,但这个答案已有两年历史了。
        【解决方案11】:

        永远不要直接使用 resize 事件,因为它会在我们调整大小时连续触发。

        使用 debounce 函数来减少过多的调用。

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

        这是我整理的small library,以巧妙地处理这个问题。

        【讨论】:

        • 我很欣赏以下信息:去抖动(现在它似乎是一个非常宝贵的概念/功能,即使我以前拒绝以这种方式使用超时),lodash(虽然我个人不相信)和解决歧义关于是否使用 addEvent 作为 addEventListener 的后备(只是因为旧的答案并没有真正明确地解决有关此问题的 cmets)
        • 仅供参考,因为您使用的是 ES6 箭头函数表示法,因此内部函数需要具有 (...arguments) =&gt; {...}(或 ...args 以减少混淆),因为 arguments 变量不再适用于它们的范围。
        • 我很清楚,sn-p 不是我的代码,这只是一个例子。
        • 很好的答案,需要解决调整大小的性能问题!去抖动是一种选择,另一种是简单的节流(如果您需要 UI 以“步骤”调整大小,这可能是一种方法)。示例见bencentra.com/code/2015/02/27/optimizing-window-resize.html
        【解决方案12】:

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

        目前,Firefox, Chrome, Safari, and Edge support it。对于其他(和更旧的)浏览器,您必须使用polyfill

        【讨论】:

          【解决方案13】:

          您可以使用以下方法,即ok for small projects

          <body onresize="yourHandler(event)">
          

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

          【讨论】:

            猜你喜欢
            • 2014-04-06
            • 1970-01-01
            • 1970-01-01
            • 2017-04-26
            • 2018-12-13
            • 2016-06-02
            相关资源
            最近更新 更多