最近的分析都是有点不温不火,基本都是基础的回顾了

今年博客的目标目前总的来说有2大块

JS版的设计模式,会用jQuery来诠释

JS版的数据结构,最近也一直在狠狠的学习中.

HTML息息相关的的样式

偏移量

offsetWidth offsetHeight offsetLeft offsetTop

offsetHeight/offsetWidth: 表述元素的外尺寸:元素内容+内边距+边框(不包括外边距)

offsetLeft/offsetTop: 表示该元素的左上角(边框外边缘)与已定位的父容器(offsetParent对象)左上角的距离。

offsetParent元素是指元素最近的定位(relative,absolute)祖先元素,可递归上溯。


客户区大小

clientWidth clientHeight

clientWidth/clientHeight: 用于描述元素的内尺寸:元素内容+两边内边距


滚动大小

scrollWidth scrollHeight scrollLeft scrollTop

scrollHeight/scrollWidth: 元素内容的总高度或宽度

scrollLeft/scrollTop:是指元素滚动条位置,它们是可写的(被隐藏的内容区域左侧/上方的像素)

浏览器窗口的滚动条位置:window对象的pageXoffset和pageYoffset, IE 8及更早版本可以通过scrollLeft和scrollTop属性获得滚动条位置


以下是网上的总结,我收集下

Chrome/FF/Safari/opera
对这些浏览器而言,window有个属性innerWidth/innerHeight包含的是整个文档的可视区域尺寸,注意,这个尺寸是包含滚动条大小的。
如果我们不计滚动条的影响,就可以直接使用这两个属性。
如果滚动条会影响(比如最大化弹出框),那么应该想另外的办法。

document.documentElementy与document.body

Document对象是每个DOM树的根,但是它并不代表树中的一个HTML元素,document.documentElement属性引用了作为文档根元素的html标记,document.body属性引用了body标记
我们这里获取常见的三个值(scrollWidth、offsetWidth和clientwidth)来比较一下

document.documentElement.scrollWidth返回整个文档的宽度
document.documentElement.offsetWidth返回整个文档的可见宽度
document.documentElement.clientwidth返回整个文档的可见宽度(不包含边框),clientwidth = offsetWidth - borderWidth

不过一般来说,我们不会给document.documentElement来设置边框,所以这里的clientwidth 与 offsetWidth一致

document.body.scrollWidth返回body的宽度
注意,这里的scrollWidth有个不一致的地方,基于webkit的浏览器(chrome和safari)返回的是整个文档的宽度,也就是和document.documentElement.scrollWidth一致,
opera和FF返回的就是标准的body 的scrollWidth,个人觉得opera和FF算是比较合理的。

document.body.offsetWidth返回body的offsetWidth
document.body.clientwidth返回body的clientwidth(不包含边框),clientwidth = offsetWidth - borderWidth

我们看上面的例子,会发现

body和documentElement的有些值是相等的,这并不是表示他们是等同的。而是因为当我们没有给body设置宽度的时候,document.body默认占满整个窗口宽度,

于是就有:

document.body.scrollWidth = document.documentElement.scrollWidth
document.body.offsetWidth = document.documentElement.offsetWidth
document.body.clientwidth = document.documentElement.clientwidth - document.body.borderWidth(body的边框宽度)

当我们给body设置了一个宽度的时候,区别就出来了。

IE9/IE8
这两个差不多,唯一的区别是IE9包含window.innerWidth属性,而IE8不包含window.innerWidth属性。
document.documentElement.scrollWidth返回整个文档的宽度,和FF等浏览器一致
document.documentElement.offsetWidth返回整个文档的可见宽度(包含滚动条,值和innerWidth一致),注意,这里和FF等浏览器又有点区别。
document.documentElement.clientwidth返回整个文档的可见宽度(不包含边框),和FF等浏览器一致。clientwidth = offsetWidth - 滚动条宽度

document.body.scrollWidth返回body的宽度,注意,这里的scrollWidth和FF等浏览器有点区别,这里并不包括body本身的border宽度。
因此例子中,相比FF少了10px。
document.body.offsetWidth返回body的offsetWidth,和FF等浏览器一致
document.body.clientwidth返回body的clientwidth(不包含边框),和FF等浏览器一致,clientwidth = offsetWidth – borderWidth

IE7与IE9/IE8的主要区别是
第一、document.documentElement.offsetWidth的返回值不一样,
参见上面说的,IE9/IE8的document.documentElement.offsetWidth包含滚动条,但是,IE7的document.documentElement.offsetWidth不包含滚动条。
第二、document.documentElement.scrollWidth返回整个文档的宽度,注意,这里和IE9/IE8、FF等浏览器又有不一致,对于IE9/IE8、FF等浏览器,scrollWidth最小不会小于窗口的宽度,但是在IE下没有这个限制,文档有多小,这个就有多小
其他倒是挺一致的。

IE6了
IE6的document.documentElement返回值与IE9/IE8没有区别(由此可见,对于document.documentElement,IE7就是个奇葩)。
话说回来,IE的document.body就是个奇葩,当没有给body设置宽度的时候,body是默认占满整个文档的(注意,其他的浏览器都是占满整个窗口),当然,最小值是整个窗口的大小,就是说body指向了根元素。
因此,在算上IE6在解析width方面的bug,和其他的浏览器的区别就淋漓尽致了。
document.body.scrollWidth返回body的宽度,和IE9/IE8/IE7一致
document.body.offsetWidth返回body的offsetWidth,注意,由于body的不同,这里的offsetWidth = scrollWidth + borderWidth
document.body.clientwidth返回body的clientwidth(不包含边框)clientwidth = offsetWidth - borderWidth
另外,有一点和IE7同样,就是document.documentElement.scrollWidth没有最小宽度限制。


源码解析

先看jQuery对窗口大小六种相似方法的生成

jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {

//执行代码

        });
});

扩展方法还是用的合并的模式,把具有相同特性的方法采用合并处理

循环生成是艺术,需要深刻了解它们的功能与共同点,然后将特异点组成一个对象,好处自然是省代码了,然后可以集中处理

执行代码

例如:.width()

为匹配的元素集合中获取第一个元素的当前计算宽度值。

return jQuery.access( this, function( elem, type, value ) {
var doc;
if ( jQuery.isWindow( elem ) ) {
return elem.document.documentElement[ "client" + name ];
} // Get document width or height
if ( elem.nodeType === 9 ) {
doc = elem.documentElement;
return Math.max(
elem.body[ "scroll" + name ], doc[ "scroll" + name ],
elem.body[ "offset" + name ], doc[ "offset" + name ],
doc[ "client" + name ]
);
} return value === undefined ?
jQuery.css( elem, type, extra ) :
jQuery.style( elem, type, value, extra );
}, type, chainable ? margin : undefined, chainable, null );

A.首先先解释下普通元素和非普通元素,

非普通元素是指window,document这些 元素对象,

普通元素是指除window,document之外的元素,如:div

B.css(width) 和 .width()之间的区别?

  • 对于非普通元素,只能使用 .width()

  • 对于普通的元素 ,他们的作用相同

  • 后者返回一个没有单位的数值(例如,400),前者是返回带有完整单位的字符串(例如,400px)。当一个元素的宽度需要数学计算的时候推荐使用.width() 方法

    C.非普通元素的获取

    如:window

    $(window).width();   //浏览器窗口
    即返回HTML的窗口,所以代码就是document.documentElement[“clientWidth”]
    if ( jQuery.isWindow( elem ) ) {
    return elem.document.documentElement[ "client" + name ];
    }
     
    document
    $(document).width();   //HTML文档窗口

    取最大值,因为可以带卷滚条溢出

    if ( elem.nodeType === 9 ) {
    doc = elem.documentElement; // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
    // whichever is greatest
    return Math.max(
    elem.body[ "scroll" + name ], doc[ "scroll" + name ],
    elem.body[ "offset" + name ], doc[ "offset" + name ],
    doc[ "client" + name ]
    );
    }
     

    D.普通元素取值

    jQuery.cssHooks

    因为有些样式不是简单的读写属性就可以的,比如width就不是简单地读取el.style.width。为了解决这个问题,jquery定义了一个属性 $.cssHooks,这里可以自定义对某个属性的get和set操作。而且jquery中就是用cssHooks来处理某些特殊属性的

    对CSS的操作都是通过统一的API调用,操作的属性是

    1. borderWidth: Object
    2. height: Object
    3. margin: Object
    4. opacity: Object
    5. padding: Object
    6. width: Object

    此时就会用jQuery.cssHooks方法处理兼容问题,

    width,height的钩子方法

    jQuery.each([ "height", "width" ], function( i, name ) {
    jQuery.cssHooks[ name ] = {
    get: function( elem, computed, extra ) {
    if ( computed ) {
    return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
    jQuery.swap( elem, cssShow, function() {
    return getWidthOrHeight( elem, name, extra );
    }) :
    getWidthOrHeight( elem, name, extra );
    }
    }, set: function( elem, value, extra ) {
    var styles = extra && getStyles( elem );
    return setPositiveNumber( elem, value, extra ?
    augmentWidthOrHeight(
    elem,
    name,
    extra,
    jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
    styles
    ) : 0
    );
    }
    };

    get 方法:

    1 节点隐藏等情况下,height、width等获取值不准,此时需利用jQuery.swap方法来获得准确值

    2 getWidthOrHeight获取准确值

    本章大体回顾下了跟HTML相关处理的10种方法与jQuery中相对应的处理流,下章再具体分析jQuery中对应每种不同兼容的处理

jQuery2.0.3源码分析系列(28) 元素大小的更多相关文章

  1. jQuery2.0.3源码分析系列之(29) 窗口尺寸

    .height() .innerHeight() .innerWidth() .outerHeight() .outerWidth() .width() 基础回顾 一般的,在获取浏览器窗口的大小和位置 ...

  2. jquery-2.0.3 源码分析 整体架构

    关键 var jQuery = function( selector, context ) { return new jQuery.fn.init(); } jQuery.fn = jQuery.pr ...

  3. jquery2源码分析系列

    学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...

  4. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  5. [转]jQuery源码分析系列

    文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...

  6. jQuery源码分析系列(转载来源Aaron.)

    声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...

  7. jQuery源码分析系列——来自Aaron

    jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...

  8. Spring mvc源码分析系列--Servlet的前世今生

    Spring mvc源码分析系列--Servlet的前世今生 概述 上一篇文章Spring mvc源码分析系列--前言挖了坑,但是由于最近需求繁忙,一直没有时间填坑.今天暂且来填一个小坑,这篇文章我们 ...

  9. MyCat源码分析系列之——结果合并

    更多MyCat源码分析,请戳MyCat源码分析系列 结果合并 在SQL下发流程和前后端验证流程中介绍过,通过用户验证的后端连接绑定的NIOHandler是MySQLConnectionHandler实 ...

随机推荐

  1. btrace使用

    btrace使用 目录btracee是btrace的解压目录 btrace/btrace是btrace的项目工程 root@ubuntu:/usr/local/bogon/btrace# tree b ...

  2. [XAML]类似WPF绑定的Binding的读取方法

    在WPF的XAML里,依赖属性可以使用基于BindingBase之类的MarkupExtensin 读取XAML时,会自动的把该BindingBase转换为BindingExpressionBase ...

  3. 【Linux】crontab 定时任务

    7月份,公司海外运营国发生数据库联接未释放,造成连接池连接不足的情况, 当时查询并没有及时解决问题, 为了避免现场同事多次人工重启系统的,因此写了个shell脚本,通过crontab 实现系统重启,但 ...

  4. Salesforce练习Case

    以下几个SFDC的Case基本覆盖了Force.com平台的一些基本操作流程,大家可以自己动手练习一下 Case 1: 在某公司的业务流程中,有零售店和销售人员两类信息,销售人员是指在零售店中工作的人 ...

  5. Ubuntu 14.04(amd64)安装Oracle11g XE(x64)

    下载Oracle安装包 下载地址:Oracle Database Express Edition 11g Release 2 for Linux x64 安装办法 1、建立oracle用户及属主 ad ...

  6. 可变字符串NSMutableString

    //可变字符串继承自字符串 //拼接 NSMutableString *string = [NSMutableString string]; [string appendString:@"今 ...

  7. mysql外键添加error1215

    在mysql创建表外键的过程中,由于操作不当,会提示cannot add foreign key constraint的错误. 造成此错误可能的原因如下: 1.数据类型不匹配,外键与其相关联的键必须数 ...

  8. js生成二维码 中间有logo

    描述: jquery.qrcode.js 是一个能够在客户端生成矩阵二维码QRCode 的jquery插件 ,使用它可以很方便的在页面上生成二维条码.此插件是能够独立使用的,体积也比较         ...

  9. 分布式数据库中的Paxos 算法

    分布式数据库中的Paxos 算法 http://baike.baidu.com/link?url=ChmfvtXRZQl7X1VmRU6ypsmZ4b4MbQX1pelw_VenRLnFpq7rMvY ...

  10. Centos7下安装mono3.10.0

    mono 3.10.0 正式发布:性能进一步改进,以前已经写过一篇  Centos 7.0 安装Mono 3.4 和Jexus 5.6.下面我们在CentOS 7上通过源码安装Mono 3.10, 需 ...