在 Internet Explorer 中触发 window.resize 事件

Posted

技术标签:

【中文标题】在 Internet Explorer 中触发 window.resize 事件【英文标题】:window.resize event firing in Internet Explorer 【发布时间】:2010-12-23 14:10:38 【问题描述】:

如您所知,在 Internet Explorer 中,当页面上的任何元素调整大小时都会触发 window.resize 事件。 页面元素是否通过分配/更改其大小来调整大小并不重要height 或 style 属性,只需向其添加子元素或其他任何方式——即使调整元素大小不会影响视口本身的尺寸。

在我的应用程序中,这导致了令人讨厌的递归,因为在我的 window.resize 处理程序中,我正在调整一些

元素的大小,这反过来又会重新触发 window.resize 等。同样,这只是一个问题即。

有没有办法防止 window.resize 在 IE 中响应页面上的元素被调整大小而触发?

我还应该提到我正在使用 jQuery。

【问题讨论】:

有趣,我不知道。我不熟悉 JQuery,但如果它的源元素不是窗口本身,它应该可以停止事件。我相信有人会想出一个编码的解决方案。 这是什么版本的IE,你能提供一些代码来显示调整元素大小会触发window.resize吗? 其他版本不应该,但它发生在 IE 8 中 我非常感谢你提出这个问题。我不停地拉扯我的头发:“为什么我的页面这么慢?”事实证明 ie8 在每一帧上都会触发 window.resize,然后我的调整大小处理程序将不得不一遍又一遍地重新定位所有内容 谢谢。可以确认它在 IE9 上也有问题。 【参考方案1】:

我刚刚发现了另一个可能对你有帮助的问题。

我正在使用 jQuery,并且我有 window.resize 事件来调用一个函数,该函数将重新定位附加到正文的 div。

现在,当我设置该附加 div 的 LEFT css 属性时,window.resize 事件会触发 NO GOOD REASON。

导致无限循环,一次又一次触发window.resize。

没有修复的代码:

$(window).resize(function()
    var onResize = function()
        //The method which alter some css properties triggers 
        //window.resize again and it ends in an infinite loop
        someMethod();
    
    window.clearTimeout(resizeTimeout);
    resizeTimeout = window.setTimeout(onResize, 10);
);

解决方案:

var winWidth = $(window).width(),
    winHeight = $(window).height();

$(window).resize(function()
    var onResize = function()
        //The method which alter some css properties triggers 
        //window.resize again and it ends in an infinite loop
        someMethod();
    

    //New height and width
    var winNewWidth = $(window).width(),
        winNewHeight = $(window).height();

    // compare the new height and width with old one
    if(winWidth!=winNewWidth || winHeight!=winNewHeight)
        window.clearTimeout(resizeTimeout);
        resizeTimeout = window.setTimeout(onResize, 10);
    
    //Update the width and height
    winWidth = winNewWidth;
    winHeight = winNewHeight;
);

所以基本上它会检查高度或宽度是否改变(只有当你实际调整窗口大小时才会发生这种情况)。

【讨论】:

阿米尔,看起来这样就行了。让我试试,我会回来告诉你它是如何工作的。 感谢您检查窗口的宽度/高度是否发生变化以查看实际窗口是否调整大小! 是 onResize global 是故意的还是你忘记了 var? 很好的解决方案 - 有与此修复程序相同的无限循环情况。 虽然检查宽度或高度是否发生变化仍然是一个好主意,但这并不能解决即使宽度和高度保持不变,resize 处理程序仍被连续触发的情况.在我的情况下,是 document 对象导致处理程序触发并导致无限循环。【参考方案2】:

这对我来说很有意义,并且似乎在 IE7 及更高版本中工作:

    //variables to confirm window height and width
    var lastWindowHeight = $(window).height();
    var lastWindowWidth = $(window).width();

    $(window).resize(function() 

        //confirm window was actually resized
        if($(window).height()!=lastWindowHeight || $(window).width()!=lastWindowWidth)

            //set this windows size
            lastWindowHeight = $(window).height();
            lastWindowWidth = $(window).width();

            //call my function
            myfunction();


        
    );

【讨论】:

【参考方案3】:

使用.one() 绑定你的resize 监听器,以便它在触发后解除绑定。然后你可以做任何你想做的事情,只要最后你重新绑定调整大小的监听器。我发现最简单的方法是将调整大小的侦听器放在匿名函数中,如下所示:

var resizeListener = function()
  $(window).one("resize",function() //unbinds itself every time it fires

    //resize things

    setTimeout(resizeListener,100); //rebinds itself after 100ms
  );

resizeListener();

从技术上讲,您不需要将 setTimeout 包裹在 resizeListener() 周围,但我会将它扔在那里以防万一并进行一些额外的节流。

【讨论】:

优秀的解决方案。请记住,函数 javascript 中的成熟对象,因此 resizeListener 可以直接传递给 setTimeout() 而不是使用字符串文字 "resizeListener();" 感谢您的提示,@user113215。我根据您的建议更新了代码。 很棒的方法,无需使用任何额外的变量或 if 语句 @brentonsrine 这解决了我的$(window).resize() 挂在IE8 上的问题。奇迹般有效。谢谢!【参考方案4】:

我通过解除绑定resize函数,重建页面然后再次绑定resize函数解决了这个问题:

function rebuild() 
   $(window).unbind('resize');
   /* do stuff here */
   $(window).bind('resize',rebuild);


$(window).bind('resize',rebuild);

编辑

绑定和取消绑定不适合 IE8。尽管 Microsoft 甚至放弃了 IE8,但您可能想尝试一下(未经测试!):

function rebuild()
   if(!window.resizing) return false;
   window.resizing=true;
   /* do stuff here */
   window.resizing=false;


window.resizing=false;
document.body.onresize=rebuild;

【讨论】:

这似乎是最优雅的解决方案,但不幸的是,它似乎并没有真正为我工作。我正在 Windows XP 上的 IE 8 和 OS X 10.9 上的 Chrome 36 中进行测试。 是的,jQuery bind 和 unbind 不能很好地与 IE8 配合使用。我怀疑他们(jQuery)会修复它,因为自 2014 年 4 月 8 日以来,即使微软不再支持 IE8/XP... 一种解决方法是在函数重建开始时设置一个全局参数,在调整大小之前检查该参数:function rebuild() if(window.resizing) return false;窗口大小调整=真; /* 在这里做一些事情 */ window.resizing=false;); =>为可读性编辑了答案【参考方案5】:

@AamirAfridi.com 的回答解决了我的问题。

编写一个通用函数来解决这些问题是个好主意:

function onWindowResize(callback) 
    var width = $(window).width(),
        height = $(window).height();

    $(window).resize(function() 
        var newWidth = $(window).width(),
            newHeight = $(window).height();

        if (newWidth !== width || newHeight !== height) 
            width = newWidth;
            height = newHeight;
            callback();
        
    );

这样使用,再也不用担心IE中的不同行为了:

onWindowResize(function() 
    // do something
);

【讨论】:

最好检查 setTimeout 的使用回调,以确保用户已完成调整窗口大小【参考方案6】:

我今天遇到了这个问题,并决定将以下内容放在我的全局包含的 javascript 文件的顶部:

var savedHeight = 0;
var savedWidth = 0;
Event.observe(window, 'resize', function (e) 
    if (window.innerHeight == savedHeight && 
        window.innerWidth == savedWidth)  e.stop(); 
    savedHeight = window.innerHeight;
    savedWidth = window.innerWidth;
);

顺便说一句,这需要原型。

【讨论】:

【参考方案7】:

unbind / bind 方法与延迟调用的混合。 它适用于 Internet Explorer 8 及更低版本,可防止恶意循环并在版本 6 和 7 上挂起。

function resizeViewport()

    // Unbind and rebind only for IE < 9
    var isOldIE = document.all && !document.getElementsByClassName;

    if( isOldIE )
        $(window).unbind( 'resize', resizeViewport );

    // ...

    if( isOldIE )
    
        setTimeout(function()
            $(window).resize( resizeViewport );
        , 100);
    


$(window).resize( resizeViewport );

【讨论】:

【参考方案8】:

你可以试试这个:

构造函数:

this.clientWidth = null;
this.clientHeight = null;

一些功能:

var clientWidth = window.innerWidth || document.documentElement.clientWidth; 
var clientHeight = window.innerHeight || document.documentElement.clientHeight;
if (clientWidth != this.clientWidth || clientHeight != this.clientHeight ) 
    this.clientWidth = clientWidth;
    this.clientHeight = clientHeight;

    ... YOUR CODE ...
 

对于 Internet Explorer、Chrome、Firefox、Opera 和 Safari:

window.innerHeight - the inner height of the browser window
window.innerWidth - the inner width of the browser window

对于 Internet Explorer 8、7、6、5:

document.documentElement.clientHeight
document.documentElement.clientWidth
    or
document.body.clientHeight
document.body.clientWidth

【讨论】:

【参考方案9】:
(function ($)
     //if ie8 -> return;
     var lastHeight = 0;
     var lastWidth = 0;
     $(window).resize(function(event)
         if (window.innerHeight == lastHeight && window.innerWidth == lastWidth)
              event.stopImmediatePropagation(); 
         lastHeight = window.innerHeight;
         lastHeight = window.innerWidth;
     );
)();

对我有用...

【讨论】:

【参考方案10】:
<pre>



var cont = 0;
var tmRsize = 100;
var lastWindowWidth = $(window).width();
var lastWindowHeight = $(window).height();

/*****redimensionamiento**********/
$(window).resize(function()

    if($(window).width() != lastWindowWidth || $(window).height() != lastWindowHeight)
    
        clearTimeout(this.id);
        this.tiempo = tmRsize;
        this.id = setTimeout(doResize, this.tiempo);
    
);

function doResize()

    lastWindowWidth = $(window).width();
    lastWindowHeight = $(window).height();

    $('#destino_1').html(cont++);

【讨论】:

【参考方案11】:

以下是我如何确定调整大小事件是由元素触发还是通过真正调整窗口大小来处理的:

如果事件的 target.nodeType 不存在,它很可能是窗口,因为页面上的任何其他元素都会有 nodeType。

下面是添加了检查的伪代码(使用 jQuery):

$(window).resize(function(event)
    if ( $(event.target.nodeType).length == 0 )
        // Anything here is run when the window was resized
        // not executed when an element triggered the resize
    
);

【讨论】:

【参考方案12】:

当元素调整大小时,我无法触发 resize 事件(但仅在 IE8 中尝试过)。

但是,当您遇到此问题时,事件对象上的 target 是什么,您能做到吗:

$(window).resize(function(e) 
    if( e.target != window ) return;
    // your stuff here
);

【讨论】:

这不起作用,因为当一个元素触发window.resize时,window.resize上的目标始终是window。这就是为什么我开始怀疑它实际上无法完成......【参考方案13】:

我的补丁:

<!--[if lte IE 7]>
<script type="text/javascript">
  window.onresize = null;       // patch to prevent infinite loop in IE6 and IE7
</script>
<![endif]-->

【讨论】:

我绝不会建议像这样弄乱 Windows 对象。【参考方案14】:

这取决于 resize 事件的内容。

我发现只有当页面包含静态内容而不是动态呈现的内容时,上述解决方案才能解决。 在现有内容将被某些触发事件(如内容重新加载功能)重新渲染的动态情况下,我们需要使用 $(document).width() 或 $(document).height() 代替。

这是因为窗口的滚动条。 如果页面有滚动条并且主要内容将通过单击“重新加载”按钮重新呈现,则滚动条在事件上消失。 在这种情况下,$(window).width() 或 $(window).height() 会被内容渲染更改,而不是实际的窗口大小调整。

【讨论】:

当链接到您自己的网站或内容(或您附属的内容)时,您must disclose your affiliation in the answer 以免被视为垃圾邮件。根据 Stack Exchange 政策,在您的用户名中包含与 URL 相同的文本或在您的个人资料中提及它不被视为充分披露。【参考方案15】:
$(window).resize(function(event)

    if (typeof event.target.tagName == 'undefined')
    
        // ...
    
);

【讨论】:

这个答案增加/改进了其他高度评价的答案怎么样?仅代码的答案不好。提供解释。

以上是关于在 Internet Explorer 中触发 window.resize 事件的主要内容,如果未能解决你的问题,请参考以下文章

Internet Explorer 的“自动完成”功能不会触发 JavaScript 事件

在 Internet Explorer 10 中重置 css 过渡

Xbox One Internet Explorer JavaScript 按键

onkeydown 和 onkeyup 事件在 Internet Explorer 8 上不起作用

在同一台计算机上运行 Internet Explorer 6、Internet Explorer 7 和 Internet Explorer 8

为啥即使在模拟 Internet Explorer 8 文档模式时,Internet Explorer 11 也不支持条件注释?