细说浏览器特性检测(1)(3)

以下为各浏览器中运行结果:

IE6   4  
IE7   1  
IE8   1  
IE9 beta   1  
Firefox 3.6   1  
Chrome 7   1  
Safari 5   1  

测试结果表明,IE6即使显式设定了宽度,在触发了hasLayout的情况下,其大小会受子元素的影响而被撑大。

jQuery将该特性用于动画效果,为了动画过程中改变一个元素的width/height时,其子元素不会溢出,jQuery做了以下几步:

保存元素当前的overflow、overflow-x、overflow-y三个样式。 将元素设置为inline-block以便修改width/height值。 将元素的overflow设为hidden,防止子元素溢出或当前元素被子元素撑开(IE6)。 在动画结束后,确保元素不会被子元素撑开(shrinkWrapBlocks为true)的情况下,才恢复overflow样式。 reliableHiddenOffsets

这个问题在上两天工作中遇到,刚好jQuery1.4.3升级了这方面的内容,使用以下代码可以检测该特性:

<table> <tbody> <tr> <td> </td> <td> abcd </td> </tr> </tbody> </table> <script type="text/javascript"> var table = document.getElementById('reliableHiddenOffsets'), td = table.getElementsByTagName('td')[0]; alert(td.offsetHeight); </script>

以下为各浏览器中运行结果:

IE6   0  
IE7   0  
IE8   21  
IE9 beta   0  
Firefox 3.6   0  
Chrome 7   0  
Safari 5   0  

只有IE8存在这个问题,那当td元素的display为none时,其高度依旧会受其所在行的高度的影响,而不是0。

这个问题的存在根本上导致了对元素可见性的判定出现差错,原本判断一个元素是否隐藏的代码是这样的:

function isHidden(element) { return element.offsetWidth == 0 || element.offsetHeight == 0; };

因为这个BUG的出现,上面的函数对于td元素失去了效果,因此需要改进为:

function isVisible(element) { return (element.offsetWidth == 0 && element.offsetHeight == 0) || (!support.reliableHiddenOffsets && getStyle(element, 'display') == 'none'); };

阅读jQuery源码的时候,会发现这一段的判断里多了一句element.style.display,这一句是用来判断元素有display值才去取来看看是不是none的,以免获取运行时样式的开销。

结语 特性检测确实很有用,有时比浏览器版本嗅探更佳可靠,但检测某些特性相当麻烦,不是必要的时候不如用浏览器嗅探。 jQuery对特性的命名真让人想砍了他们团队。 有些特性可以重现的浏览器版本之低令人惊讶,在多数项目中完全可以不考虑,如checkClone。jQuery本身为了兼容做了太多的假设,个人认为有一些完全可以抛弃,比如以后会说的getBoundingClientRect问题。 另外还有2个关于事件上的特性检测,由于事件的特性检测是一个通用的话题,会有今后专门写文讲述,因此就不在本文中赘述了。 jQuery每一个小版本的改进都很大,特别在细节方面,这些都是要通过阅读源码不断发掘的,前端的世界就是这么多变(叹)。 本文所用的示例可以点此查看,具体可以查看源代码,本文所述的各个问题/BUG都没在网上找到比较权威的说明,还请见谅!


[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

您可能感兴趣的文章:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdxyjp.html