当前位置: 代码迷 >> 跨浏览器开发 >> resize 事件的兼容性有关问题研究
  详细解决方案

resize 事件的兼容性有关问题研究

热度:8505   发布时间:2013-02-26 00:00:00.0
resize 事件的兼容性问题研究
先了解一下浏览器拖拉触发resize的方式。 
例如在xp的系统性能选项中,设置是否“拖拉时显示窗口内容”会有不同的拖拉效果: 
选择是的话,由于内容会跟着浏览器的拖拉同时渲染页面,导致resize事件的持续触发; 
选择否的话,内容在拖拉完成才会渲染,并触发resize事件,即在拖拉过程中resize事件只会在确定后才触发一次; 
不过ff有点特殊,即使选择否,它右下角的触发点还是会按照拖拉同时渲染页面的方式触发的。 
后面测试时建议选择否,会比较准确看到结果。 

再看看resize事件的支持情况。 
在ie,haslayout的块级和内联元素都支持onresize事件,其他浏览器只有window对象支持。 
而ie6/7跟ie8的支持程度也有不同,测试以下代码: 
Assembly code
<!doctype html><body><div id="show">0</div><div id="div" style="border:1px solid #000"></div><script>var i = 0;div.onresize = function(){ show.innerHTML = ++i; }setTimeout('div.innerHTML="test"', 1000)setTimeout('div.style.height="50px"', 2000)</script></body></html>

在ie8两种情况都会触发onresize,但ie6/7只有第二种情况触发。 
鉴于情况比较复杂,程序在使用window作为容器时才绑定事件,其他情况请自行设置。 

resize事件有不少的问题,处理时要小心。 
chrome的resize有一个问题(bug?),每次触发resize都会执行两次事件,或者说会触发两次。 
而ie就复杂了,window, body和documentElement的resize会相互影响。 
在ie8测试以下代码: 
Assembly code
<!doctype html><style>html,body{border:5px solid #06F;}</style><body><div id="div" style="height:100px;"></div></body></html><script>window.onresize = function(){ div.innerHTML += "window, "; }//document.documentElement.onresize = function(){ div.innerHTML += "documentElement, "; }//document.body.onresize = function(){ div.innerHTML += "body, "; }</script>
当上下拖放时,onresize只会触发一次,但左右拖放时会触发两次。 
换成documentElement会有差不多的结果,两个一起用的话左右拖放时documentElement会触发两次,window一次。 
只设置body的话感觉就正常了,上下左右都只会触发一次。 
而documentElement和body同时设置的效果跟documentElement和window的效果差不多。 
如果window和body同时设置的话,后一个会覆盖前一个。 
看来window和body的onresize对应的是同一个对象事件,可能为了在body设置也能做到window一样的效果。 
个人推测,window和documentElement多出的一次,可能是同时触发了body的resize造成的。 
ps:onresize时,用srcElement获取不到触发元素,所以确定不了是哪个元素触发。 
ie7跟ie8的结果差不多,ie6就有些不同,不过估计也是盒模式的不同造成的。 
具体产生原因还不清楚,这里我也很糊涂。 

虽然问题弄不清楚,解决方法还是有的。 

要绑定resize就是因为视框范围发生了变化,要重新设置视框范围,那么可以通过看两次resize之间视框范围有没有变化来确实是否执行程序。 
在上次写的Lazyload效果中,就是通过clientWidth和clientHeight来判断的: 
Assembly code
this.resizeDelay = function(){    var clientWidth = container.clientWidth,        clientHeight = container.clientHeight;    if( clientWidth != width || clientHeight != height ) {        width = clientWidth; height = clientHeight;        oThis._delay( oThis.resize );    }};

ps:如果只需针对window,直接用innerHeight/innerWidth就不用理会文档模式了。

------解决方案--------------------------------------------------------
cloudgamer 都来了,欢迎欢迎啊,最近貌似51js很冷淡的说。
------解决方案--------------------------------------------------------
lz威武,很实用的东西。

但是第一个测试用例有点儿兼容性问题,建议修改成这样:
HTML code
<!doctype html><script>    window.onload = function() {        var div=document.getElementById("div");        var i = 0;        div.onresize = function() {            show.innerHTML = "触发了resize事件";        }        setTimeout(function(){           div.innerHTML="test";        }, 1000)        setTimeout(function(){           div.style.height="50px"        }, 2000)    }</script><div id="show">0</div><div id="div" style="border:1px solid #000"></div>
  相关解决方案