首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议131:慎重使用offsetWidth和offsetHeight

关灯直达底部

可以使用offsetWidth和offsetHeight属性来获取元素的尺寸,其中offsetWidth表示元素在页面中所占据的总宽度,offsetHeight表示元素在页面中所占据的总高度。例如:


<p >

<p >

<p >

<p >

<p></p>

</p>

</p>

</p>

</p>

<script language=/"javascript/"type=/"text/javascript/">

var p=document.getElementById(/"p/");

var w=p.offsetWidth;//返回元素的总宽度

var h=p.offsetHeight;//返回元素的总高度

</script>


上面的示例在IE的“怪异”模式下和支持DOM模型的浏览器中解析结果差异很大,其中在IE“怪异”模式下解析返回宽度为13像素,高度为26像素,而在支持DOM模型的浏览器中返回高度和宽度都为18像素(但是FF返回19像素,因为小数取舍方法不同)。

IE“怪异”模式是一种非标准的解析方法,与标准模式相对应,主要是IE为了兼容大量传统布局的网页而采用的。“怪异”模式在IE 6.0以下版本中存在,但在IE 6.0及其以上版本中,如果将页面明确设置为“怪异”模式显示,或者HTML文档的DOCTYPE(文档类型)没有明确定义,也会按“怪异”模式进行解析。

根据示例中内行样式定义的值,可以算出最内层元素的宽和高都为12.5像素,实际取值为12像素。但对于IE“怪异”解析模式来说,样式属性width和height的值就是元素的总宽度和总高度。由于IE是根据四舍五入法处理小数部分的,因此该元素的总高度和总宽度都是13像素。同时,由于IE模型定义每个元素都有一个默认行高,即使元素内不包含任何文本,因此实际高度就显示为26像素。

而对于支持DOM模型的浏览器来说,它们认为元素样式属性中的宽度和高度仅是元素内部包含的内容区域的尺寸,而元素的总高度和总宽度应该加上补白和边框,由于元素默认边框值为3像素,因此最后计算的总高度和总宽度都是18像素。至于,Firefox返回值为19像素,是因为它在处理小数部分时,并没有完全舍去,而是根据条件和环境的不同增加了1个像素值。

也许offsetWidth和offsetHeight属性是获取元素尺寸的最好的方法,但在实践中会发现:当为元素定义隐藏属性,即设置样式属性display的值为none时,元素的尺寸总为0,代码如下:


<p></p>

<script language=/"javascript/"type=/"text/javascript/">

var p=document.getElementById(/"p/");

var w=p.offsetWidth;//返回0

var h=p.offsetHeight;//返回0

</script>


这种情况还会发生在父级元素的display样式属性为none时,即使当前元素没有设置隐藏显示,根据继承关系也会将其隐藏显示,此时offsetWidth和offsetHeight属性值都是0。总之,对于隐藏元素来说,不管它的实际高度和宽度是多少,最终读取的offsetWidth和offsetHeight属性值都是0。

要解决这个问题,还需要自定义函数专门弥补offsetWidth和offsetHeight属性的缺陷。具体设计思路:先判断元素的样式属性display的值是否为none,如果不是,则直接调用offsetWidth和offsetHeight属性读取元素的宽和高即可。如果元素的样式属性display的值为none,则可以暂时显示元素,然后读取它的尺寸,读取完之后再把它恢复为隐藏样式。为此,不妨先设计两个小的功能函数,通过它们可以分别重设和恢复元素的样式属性值。代码如下:


//重设元素的样式属性值

//参数:e表示重设样式的元素,o表示要设置的值,它是一个对象,可以包含多个名-值对

//返回值:重设样式的原属性值,以对象形式返回

function setCSS(e,o){

var a={};

for(var i in o){

a[i]=e.style[i];

e.style[i]=o[i];

}

return a;

}

//恢复元素的样式属性值

//参数:e表示重设样式的元素,o表示要恢复的值,它是一个对象,可以包含多个名-值对

//返回值:无

function resetCSS(e,o){

for(var i in o){

e.style[i]=o[i];

}

}


有了这两个小的功能函数后,再自定义函数getW和getH,不管元素是否被隐藏显示,这两个函数能够获取元素的宽度和高度。具体实现代码如下:


//获取元素的存在宽度

//参数:e表示元素

//返回值:存在宽度

function getW(e){

if(getStyle(e,/"display/")!=/"none/")return e.offsetWidth||fromStyle(getStyle(e,/"width/"));

var r=setCSS(e,{

display:/"/",

position:/"absolute/",

visibility:/"hidden/"

});

var w=e.offsetWidth||fromStyle(getStyle(e,/"width/"));

resetCSS(e,r);

return w;//返回存在宽度

}

//获取元素的存在高度

//参数:e表示元素

//返回值:存在高度

function getH(e){

if(getStyle(e,/"display/")!=/"none/")return e.offsetHeight||fromStyle(getStyle(e,/"height/"));

var r=setCSS(e,{

display:/"/",

position:/"absolute/",

visibility:/"hidden/"

});

var h=e.offsetHeight||fromStyle(getStyle(e,/"height/"));

resetCSS(e,r);

return h;

}


最后,调用getW和getH扩展函数来测试它的性能:


<p></p>

<script language=/"javascript/"type=/"text/javascript/">

var p=document.getElementById(/"p/");

var w=p.offsetWidth;//返回0

var h=p.offsetHeight;//返回0

var w1=getW(p);//返回200

var h1=getH(p);//返回200

</script>