在进入源码分析前,我们先来点基础知识。下面这张图画的是元素的盒式模型,这个没有兼容性问题,有问题的是元素的宽高怎么算。以宽度为例,ff中 元素宽度=content宽度,而在ie中 元素宽度=content宽度+border宽度+padding宽度。IE8中加入了box-sizzing,该css属性有两个值:border-box、content-box分别对应ie和ff中元素宽度的工作方式。

dojo/dom-geometry元素大小

  偏移量:offsetLeft、offsetTop、offsetWidth、offsetHeight

  offsetLeft:包含元素的左内边框到元素的左外边框之间的像素距离。

  offsetTop:包含元素的上内边框到元素的上外边框之间的相续距离。

  offsetWidth:包括元素的内容区宽度、左右内边距宽度、左右边框宽度、垂直方向滚动条的宽度之和。

  offsetHeight:包括元素内容区高度、左右内边距高度、左右边框高度、水平方向滚动条的高度之和。

  包含元素的引用在offsetParent属性中,offsetParent属性不一定与parentNode属性相同,比如<td>的offsetParent是<table>而不是<tr>.

dojo/dom-geometry元素大小

  客户区大小:clientWidth、clientHeight

  clientWidth:元素的内容区宽度+内边距宽度

  clientHeight:元素的内容区高度+内边距高度

dojo/dom-geometry元素大小

  滚动大小:scrollTop、scrollLeft、scrollWidth、scrollHeight。滚动大小指的是包含滚动内容的元素大小。

  scrollTop:被隐藏在内容区域上方的像素数。

  scrollLeft:被隐藏在内容区域左侧的像素数。

  通过设置以上两个属性可以改变元素的滚动位置。

  scrollWidth:在没有滚动条情况下,元素的内容的宽度。

  scrollHeight:在没有滚动条情况下,元素内容的高度。

dojo/dom-geometry元素大小

 

  以上基础知识,对我们分析dom-geometry模块的代码会有不少帮助。下面我们进入源码学习阶段。

  dom-geometry模块封装了许多跟盒式模型相关的函数,主要涉及:content、padding、border、margin四方面。在前面的几篇文章中我们多次提到,前端js库中对dom操作的封装最终都是要用到DOM原生的API。在此模块中,最常用的原生方法就是elemet.ownerDocument.defaultView.getComputedStyle和element.getBoundingClientRect。尽管这两个方法都存在着兼容性问题,但我们都有适当的方法来解决。

   getComputedStyle方法已经在dom-style模块中介绍过(ie中使用element.currentStyle其他浏览器利用原生的getComputedStyle,在webkit中对于不在正常文档流中的元素先改变display),这里简单看一下:

 1 if(has("webkit")){
 2         getComputedStyle = function(/*DomNode*/ node){
 3             var s;
 4             if(node.nodeType == 1){
 5                 var dv = node.ownerDocument.defaultView;
 6                 s = dv.getComputedStyle(node, null);
 7                 if(!s && node.style){
 8                     node.style.display = "";
 9                     s = dv.getComputedStyle(node, null);
10                 }
11             }
12             return s || {};
13         };
14     }else if(has("ie") && (has("ie") < 9 || has("quirks"))){
15         getComputedStyle = function(node){
16             // IE (as of 7) doesn't expose Element like sane browsers
17             // currentStyle can be null on IE8!
18             return node.nodeType == 1 /* ELEMENT_NODE*/ && node.currentStyle ? node.currentStyle : {};
19         };
20     }else{
21         getComputedStyle = function(node){
22             return node.nodeType == 1 /* ELEMENT_NODE*/ ?
23                 node.ownerDocument.defaultView.getComputedStyle(node, null) : {};
24         };
25     }
26     style.getComputedStyle = getComputedStyle;
View Code

相关文章: