jQuery2.0.3源码分析系列之(29) 窗口尺寸
- .height()
- .innerHeight()
- .innerWidth()
- .outerHeight()
- .outerWidth()
- .width()
基础回顾
一般的,在获取浏览器窗口的大小和位置时,有以下几个属性可以使用:
在不同的浏览器中,以下12个属性所代表的意义也是不一样的
特别需要注意的是,当使用或者不使用<!DOCTYPE>声明显示一个文档的时候,以上12个属性的意义也会发生变化。
特在IE 9中,无论是否使用<!DOCTYPE>声明显示一个文档,document.documentElement和document.body中的相关属性的意义总是相同的。这点与IE 6/7/8表现不一样。
正常情况:Firefox/Chrome/Safari(带<!DOCTYPE>声明)
窗口显示区(可视区域)的宽度和高度,包括滚动条区域
window.innerHeight
window.innerWidth窗口显示区(可视区域)的宽度和高度,不包括滚动条区域
document.documentElement.clientHeight
document.documentElement.clientWidth<body>元素的宽度和高度(注意,包括了不可见的区域)
document.body.clientHeight
document.body.clientWidth当前页面相对于窗口显示区左上角的 X /Y位置,即水平/垂直滚动条已滚动的距离
window.pageXOffset
window.pageYOffsetFirefox:当前页面相对于窗口显示区左上角的 X /Y位置,即水平/垂直滚动条已滚动的距离,同window.pageXOffset/pageYOffset
Chrome/Safari:总为0
document.documentElement.scrollLeft
document.documentElement.scrollTopFireFox:总为0
Chrome/Safari:当前页面相对于窗口显示区左上角的 X /Y位置,即水平/垂直滚动条已滚动的距离,同window.pageXOffset/pageYOffse
document.body.scrollLeft
document.body.scrollTop如下一图说明所有问题
首先先解释下普通元素和非普通元素,
非普通元素是指window,document这些 元素对象,
普通元素是指除window,document之外的元素,如:div
innerHeight属性:窗口中文档显示区域的高度,不包括菜单栏、工具栏等部分。该属性可读可写。
IE不支持该属性,IE中body元素的clientHeight属性与该属性相同。
innerWidth属性:窗口中文档显示区域的宽度,同样不包括边框。该属性可读可写。
IE不支持该属性,IE中body元素的clientWidth属性与该属性相同。
clientHeight与clientWidth属性是只读的。
另外,IE不支持outerWidth、outerHeight属性。
兼容IE与DOM浏览器,如何获取窗口中文档显示区域的宽度及高度,使用?:条件语句,如下:
windows.innerWidth ? windows.innerWidth : document.body.clientWidth;
windows.innerHeight ? windows.innerHeight : document.body.clientHeight
源码实现
window,document
$(window).height() 代表了当前可见区域的大小
$(document).height() 则代表了整个文档的高度
注意当浏览器窗口大小改变时(如最大化或拉大窗口后) $(window).height() 随之改变,但是$(document).height()是不变的。
https://github.com/jquery/jquery/pull/764
window 反映的是视图窗口,没有用window.innerWidth
源码是通过document.documentElement
return elem.document.documentElement[ "client" + name ];
因为有些样式不是简单的读写属性就可以的,比如width就不是简单地读取el.style.width。为了解决这个问题,jquery定义了一个属性 $.cssHooks,这里可以自定义对某个属性的get和set操作。而且jquery中就是用cssHooks来处理某些特殊属性
具体涉及了:
- borderWidth: Object
- height: Object
- margin: Object
- opacity: Object
- padding: Object
- width: Object
做dom选择器的时候,需要考虑各种兼容问题,所以就算是定位2X的源码,只考虑标准的w3c,不免也要额外才处理一些属性
比如盒子模型的解释:
说到 IE 的 bug,它对于“盒模型”的错误解释:在 IE5.x 以及 Quirks 模式的 IE6/7 中,将 border 与 padding 都包含在 width 之内。这为前端工程师的工作平添了不少麻烦,几户每个需要定义尺寸的 box 都要思量一下:是否触发了“盒模型 bug”?
同时,由于另一撮浏览器对标准的遵从,我们在精确定义一个在有限空间内显示的 box 时,也需要计算一下:留给它的空间只有那么大,刨去 border 和 padding,我们该把它的 width 写成多少呢?
这种情况在 CSS3 时代有了改善,得益于这个叫做 box-sizing 的属性,它具有“content-box”和“border-box”两个值。
定义 box-sizing: content-box; 时,浏览器对盒模型的解释遵从我们之前认识到的 W3C 标准;
定义 box-sizing: border-box; 时,浏览器对盒模型的解释与 IE6 相同;
我们看看width,height方法
jQuery还提供两个单独的API,width, height获取元素的长宽,可以取得隐藏元素的长宽
这里是属于cssHooks处理
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
);
}
};
});出于性能的考量,浏览器对隐藏元素的样式是统统不计算的,有一套默认值返回给你,对于长宽就是0。对于动画来说,这有点不方便,比如show, slideDown等特效!因此jQuery等偷偷让它们显示出来,取得精确值,再隐藏回来,这个是由jquery.swap方法来处理
所以最终通过getWidthOrHeight方法获取了width,height
当然正常情况下offsetWidth,offsetHeigth是可以了,但是某些元素比如SVG,MathML返回尺寸出错(这里不考虑)
即便如此CSS3还增加了一个box-sizing选择盒子模型,于是有了augmentWidthOrHeight这个方法。
augmentWidthOrHeight方法其实就是对IE盒子模型的一个处理
所以最终的尺寸值其实是
offsetWidth/offsetHeigth + augmentWidthOrHeight方法
return ( val +
augmentWidthOrHeight(
elem,
name,
extra || ( isBorderBox ? "border" : "content" ),
valueIsBorderBox,
styles
)
) + "px";augmentWidthOrHeight
1.8增加了对css属性box-sizing的支持,需要注意与1.7.2的区别了。
1.7.2及以前的版本无论是否定义box-sizing: border-box返回的都是盒模型中元素内容的宽度或高度,不包括padding和border。
augmentWidthOrHeight方法是特别针对盒子模型的处理
例如,假如您需要并排放置两个带边框的框,可通过将 box-sizing 设置为 "border-box"。这可令浏览器呈现出带有指定宽度和高度的框,并把边框和内边距放入框中。
<style>
div { width:60px; height:60px; margin:5px; float:left; }
#aaron-box-test {
box-sizing: border-box;
-moz-box-sizing: border-box;
width: 500px;
padding: 5px;
border: 5px solid gold;
}
</style>
</head>
<body>
<div id="aaron-box-test"></div>
<script>
var $el = $('#aaron-box-test')
var w = $el.width(); //
</script>定义了
box-sizing = border-box , width = 480px
box-sizing = content-box ,width = 500px
IE6/7不支持box-sizing,输出的依然是500。但支持该熟悉的浏览器此时输出的结果则是480(刨去了盒模型的border和padding
border遵循的是IE的标准,跟IE6一样,将 border 与 padding 都包含在 width 之内
当然盒子模型的好处也有的:无论如何改动 border 与 padding 的值,都不会导致 box 总尺寸发生变化,也就不会打乱页面整体布局。而在 Firefox 等现代浏览器下,如果我们要改变一下 padding 的值,就不得不重新计算 box 的 width
innerWidth
为匹配的元素集合中获取第一个元素的当前计算宽度值,包括padding,但是不包括border。
这个方法返回元素的宽度,包括左边和右边的padding,单位是像素。
这个方法不适用于
window
anddocument
对象,可以使用.width()
代替。jQuery对CSS的处理统一调用了 jQuery.css( elem, type, extra ) 处理,不同的是这里额外的提供一个参数extra
当为innerWidth其实就满足这一条件,所以 extra: "padding", 即额外还包行padding的处理
对width操作是属性有兼容问题要处理的
故而代码要走钩子处理,此刻就是get方法,流程如上
其中有比较大的hack
比如Edwards大神的
curCSS方法中用于在标准浏览器下转换百分比值为更有用的像素值
整个流程代码看下来,你就发现jQuery的处理真的是细到极致,你可能就一个简简单单的width(), 实现的背后可能是几百 上千行的代码量!!!
jQuery2.0.3源码分析系列之(29) 窗口尺寸的更多相关文章
- jQuery2.0.3源码分析系列(28) 元素大小
最近的分析都是有点不温不火,基本都是基础的回顾了 今年博客的目标目前总的来说有2大块 JS版的设计模式,会用jQuery来诠释 JS版的数据结构,最近也一直在狠狠的学习中. HTML息息相关的的样式 ...
- jquery-2.0.3 源码分析 整体架构
关键 var jQuery = function( selector, context ) { return new jQuery.fn.init(); } jQuery.fn = jQuery.pr ...
- jquery2源码分析系列
学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- MyCat源码分析系列之——结果合并
更多MyCat源码分析,请戳MyCat源码分析系列 结果合并 在SQL下发流程和前后端验证流程中介绍过,通过用户验证的后端连接绑定的NIOHandler是MySQLConnectionHandler实 ...
- MyCat源码分析系列之——SQL下发
更多MyCat源码分析,请戳MyCat源码分析系列 SQL下发 SQL下发指的是MyCat将解析并改造完成的SQL语句依次发送至相应的MySQL节点(datanode)的过程,该执行过程由NonBlo ...
随机推荐
- 【原】iOS学习之应用之间的操作
关于应用之间的相互操作,小编一直觉得非常高大上,在一次面试中被面试官一顿暴虐,今天小编就决定学习一下!经过一顿度娘,找到一些博客,不过都比较凌乱,我就打算自己整理一下! 首先要说的是每一个APP都可以 ...
- webdav不识别软链接?解决办法?
webdav不识别软链接?解决办法? 在使用webdav实现公网存储共享的时候,发现webdav并不支持软链接的共享,如下源代码可以100%确定这个问题 /* ### for now, only pr ...
- CS0103: The name ‘Scripts’ does not exist in the current context解决方法
转至:http://blchen.com/cs0103-the-name-scripts-does-not-exist-in-the-current-context-solution/ 更新:这个bu ...
- [BZOJ2072][POI2004] MOS过桥
Description 一个夜晚一些旅行者想要过桥. 他们只有一个火把. 火把的亮光最多允许两个旅行者同时过桥. 没有火把或者多于2个人则不能过桥.每个旅行者过桥都需要特定的时间, 两个旅行者同时过桥 ...
- Linux基础命令-有关于目录的命令
1. 查看帮助: [root@oracle ~]# man cd //查看 cd 指令的帮助文档 2. 显示当前工作目录: [root@oracle ~]# pwd/root 3. 列出当前目录下的内 ...
- 腾讯网2016回响中国:华清远见荣获2016年度知名IT培训品牌
12月1日,由腾讯网主办的“2016回响中国·腾讯网教育年度盛典”上,揭晓了“2016腾讯网教育年度总评榜”榜单.高端IT就业培训专家——华清远见教育集团凭借自身优质的高薪IT就业服务优势成功入围,荣 ...
- IntelliJ IDEA - 热部署插件JRebel 安装使用教程
IntelliJ IDEA - JRebel 安装使用教程 JRebel 能做什么? JRebel 是一款热部署插件.当你的 Java-web 项目在 tomcat 中 run/debug 的时候 , ...
- WeX5学习笔记
目录 WeX5学习笔记... 1 1.轻松看透WeX5产品能力和技术... 1 2.WeX5可以怎么玩?... 3 一.纯本地App. 3 二.关联一个网站,希望默认就打开某页... 4 三.UI设计 ...
- flash小游戏在Kongregate上线——BasketBall Master(篮球大师)
小游戏地址,欢迎上去留言评论.游戏完成度没有达到期望水平,只能算完成了核心玩法吧,一些其他构想来不及实现. BasketBall Master(篮球大师) 这个小游戏很早之前就基本做好了,只因有些细节 ...
- 关于Hibernate的Dialect
org.hibernate HibernateException Dialect must be explicitly set :*** 使用Hibernate,有时候会遇到类似上面的异常. 使用 ...