jquery好比一把锋利的匕首,用的好能让你效率倍增,用的不好能让你反受其害。
最近公司的产品出现了严重的内存泄漏,经过分析是jquery造成的,可能不是jquery本身造成,但jquery的存在导致程序员的事件滥用,dom操作过于频繁,而且jquery+iframe特别是嵌套iframe时,那内存泄漏就是杠杠的了。
痛定思痛之后,公司决定了去掉jquery的依赖,对公司的组件和产品界面进行全面的改造,自然需要用原生js来实现jquery里面常用的一些方法。
今天我们介绍下height()方法的实现。
(一)如果存在行内样式
如果html代码是
<div id="box" class="test" style="height:100px">
1111111
</div>
发现
$("#box").height()=document.getElementById("box").style.height;//输出都是100px
(二)如果不存在行内样式,而是定义在css文件中
如果html代码是
<style type="text/css">
#box{
height:100px;
}
</style>
<div id="box" class="test">
1111111
</div>
则结果并不相等了
$("#box").height()//输出100px;
document.getElementById("box").style.height;//则是空咯 因为这种方式只能从行内样式获取对应的值
那就改成如果行内样式中获取高度为0时则从css中获取吧
_getStyleValue:function(elObj,attr){
elObj = GoingUtils.getElObj(elObj);
if(elObj.currentStyle){ //IE
return elObj.currentStyle[attr];
}else{
return getComputedStyle(elObj)[attr]; //Firefox
}
}
parseFloat(GoingUtils._getStyleValue(elObj,"height"));
(三)如果class中也没定义height样式,ie中会输出auto,需要计算
以为大功告成,欣喜的开始使用,谁知道html代码如果写成下面这种方式,在ie上又不好使了
<style type="text/css">
.test{
background-color: #FF0;padding:100px;border:100px solid #023456;
}
</style>
<div id="box" class="test">
1111111
</div>
会发现输出结果是:
$("#box").height(); //输出21
而
GoingUtils._getStyleValue(elObj,"height") //输出是auto
只能通过offsetHeight从新计算,注意jquery里面获取的高度是不包含边框和padding的 所以需要通过offsetHeight来减去相应的边框和边距。
var borderTopWidth = GoingUtils._getStyleValue(elObj, "borderTopWidth");
var borderBottomWidth = GoingUtils._getStyleValue(elObj, "borderBottomWidth");
var paddingTop = GoingUtils._getStyleValue(elObj, "paddingTop");
var paddingBottom = GoingUtils._getStyleValue(elObj, "paddingBottom")
var backHeight = parseFloat(elObj.offsetHeight) - parseFloat(borderTopWidth) - parseFloat(borderBottomWidth) - parseFloat(paddingTop) - parseFloat(paddingBottom);
return parseFloat(backHeight);
以为大功告成,那就大错特错了,如果html代码是这样的
<style type="text/css">
.test{
background-color: #FF0;padding:100px;border:100px solid #023456;display: none;
}
</style>
<div id="box" class="test">
1111111
</div>
结果是:
$("#box").height()//输出21
而原生的js获取到的还是0
(四)元素是display:none,需要设置显示后再进行获取高度
思路还是比较简单就是把元素显示出来,计算出高度后,再将元素隐藏。
(五)最终代码应该如下:
_getStyleValue:function(elObj,attr){
elObj = GoingUtils.getElObj(elObj);
var view = elObj.ownerDocument.defaultView;
if (!view || !view.opener) {
view = window;
}
if(elObj.currentStyle){ //IE
return elObj.currentStyle[attr];
}else{
return view.getComputedStyle(elObj)[attr]; //Firefox
}
},
isShow: function (elObj) {
elObj = GoingUtils.getElObj(elObj);
var display = GoingUtils._getStyleValue(elObj, 'display');
if (display === 'none') {
return false;
} else {
return true;
}
},
//获取某个元素的高度
getElHeight: function (elObj) {
//如果传入的不是对象是字符串 则通过字符串转换成对象
elObj = GoingUtils.getElObj(elObj);
if (elObj != null&&GoingUtils.isShow(elObj)) {
//从style中获取对应的高度
if (elObj.style.height != null && elObj.style.height.length > 0) {
return parseFloat(elObj.style.height);
}
//如果elObj.style.height为空 则从css里面获取是否定义了height信息如果定义了 则读取css里面定义的高度height
if(parseFloat(GoingUtils._getStyleValue(elObj,"height"))>0) {
return parseFloat(GoingUtils._getStyleValue(elObj,"height"));
}
//如果从css里获取到的值不是大于0 可能是auto 则通过offsetHeight来进行计算
if (elObj.offsetHeight > 0) {
var borderTopWidth = GoingUtils._getStyleValue(elObj, "borderTopWidth");
var borderBottomWidth = GoingUtils._getStyleValue(elObj, "borderBottomWidth");
var paddingTop = GoingUtils._getStyleValue(elObj, "paddingTop");
var paddingBottom = GoingUtils._getStyleValue(elObj, "paddingBottom")
var backHeight = parseFloat(elObj.offsetHeight) - parseFloat(borderTopWidth) - parseFloat(borderBottomWidth) - parseFloat(paddingTop) - parseFloat(paddingBottom);
return parseFloat(backHeight);
}
return 0;
} else {
//将元素显示出来 获取高度 再将元素隐藏掉
GoingUtils.attrEl(elObj,'style',"visibility:hidden;display:block !important;");
var height=GoingUtils.getElHeight(elObj);
elObj.removeAttribute('style');
return height;
}
return parseFloat(elObj.style.height);
},