jQuery offset()源码解析
首先是原型上的offset方法,根据arguments判断到底是取值还是设值。如果是设置,就遍历调用静态方法jQuery.offset.setOffset
如果是取值。那么就是从"var docElem,win"这里开始了。
jQuery.fn.offset = function( options ) {
if ( arguments.length ) {//设置元素坐标
return options === undefined ?//如果传入的参数是undefined,直接返回
this :
this.each(function( i ) {//遍历然后调用jQuery.offset.setOffset
jQuery.offset.setOffset( this, options, i );
});
}
var docElem, win,
elem = this[ 0 ],
box = { top: 0, left: 0 },
doc = elem && elem.ownerDocument;//当前文档
if ( !doc ) {
return;
}
docElem = doc.documentElement;
// Make sure it's not a disconnected DOM node
if ( !jQuery.contains( docElem, elem ) ) {//如果元素没有被documentElement包含,就返回 0 0
return box;
}
// If we don't have gBCR, just use 0,0 rather than error
// BlackBerry 5, iOS 3 (original iPhone)
if ( typeof elem.getBoundingClientRect !== core_strundefined ) {//如果元素有getBoundingClientRect方法
box = elem.getBoundingClientRect();//调用该方法
}
win = getWindow( doc );//如果是window就返回window,如果是document,返回document.defaultView
return {
//元素相对于视窗的距离+滚动距离-边框宽度
top: box.top + win.pageYOffset - docElem.clientTop,
left: box.left + win.pageXOffset - docElem.clientLeft
};
};
取值中,它考虑了元素没有被documentElement包含的情况,没有渲染,自然是没有offset的,于是它很神奇的返回了{"top":0,"left":0}。
因为看的是jQuery 2.x的版本,这里它用到了getBoundingClientRect方法,从名字就可以看出,它返回的是相对于视窗的距离,这不是我们需要的offset,jQuery.offset返回的是相对于文档的距离,所以还要做进一步的计算:
return {
//元素相对于视窗的距离+滚动距离-边框宽度
top: box.top + win.pageYOffset - docElem.clientTop,
left: box.left + win.pageXOffset - docElem.clientLeft
};
关于getWindow,看看函数声明:
function getWindow( elem ) {
return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}
如果elem是window,直接返回window,如果是document,则返回document.defaultView。
不是很理解为什么要使用document.defaultView,群里的小伙伴说可能是多frame的情况
然后我在stackoverflow上找到的帖子 http://stackoverflow.com/questions/9183555/whats-the-point-of-document-defaultview 也有类似的答案,然后另一种可能是为了修复Firefox 3.6中getComputedStyle的bug(⊙o⊙)…
接下来是静态方法设置offset。。。
jQuery.offset = {
setOffset: function( elem, options, i ) {
var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
position = jQuery.css( elem, "position" ),//获取当前元素的position属性
curElem = jQuery( elem ),//缓存当前元素
props = {};
// Set position first, in-case top/left are set even on static elem
if ( position === "static" ) {//如果原元素是静态定位的,改成相对定位
elem.style.position = "relative";
}
curOffset = curElem.offset();//获取当前元素的offset
curCSSTop = jQuery.css( elem, "top" );
curCSSLeft = jQuery.css( elem, "left" );
//如果元素的position为absolute或者fixed,而且其top和left属性中至少有一项的值是auto,calculatePosition为true
calculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
if ( calculatePosition ) {
curPosition = curElem.position();//获取元素相对于父元素的偏移位置
curTop = curPosition.top;
curLeft = curPosition.left;
} else {//如果calculatePosition为false,元素相对定位或者原本就有top、left值
curTop = parseFloat( curCSSTop ) || 0;
curLeft = parseFloat( curCSSLeft ) || 0;
}
if ( jQuery.isFunction( options ) ) {//如果options是函数,遍历调用
options = options.call( elem, i, curOffset );
}
//计算props值,因为offset是相对文档定位,新的css的top/left值
//需要根据原来的offset和css的top/left值计算
if ( options.top != null ) {
props.top = ( options.top - curOffset.top ) + curTop;
}
if ( options.left != null ) {
props.left = ( options.left - curOffset.left ) + curLeft;
}
//如果有using这个参数,可以调用using方法
if ( "using" in options ) {
options.using.call( elem, props );
} else {//如果没有,设置css偏移。
curElem.css( props );
}
}
};
关于using这个选项,之前在jQuery API中没有看到过。发现隐藏技能了(⊙o⊙)…??
好吧,刚在百度上试了下
$('#page').offset({"top":1000,"left":100,"using":function(prop){console.log(prop)}});
//Object {top: -302, left: 100}
jQuery offset()源码解析的更多相关文章
- jquery 部分函数源码解析
JSON.stringify源码(在看extend文档的时候看到) var object1 = { apple: 0, banana: {weight: 52, price: 100}, cherry ...
- jquery extend源码解析
$.extend(obj1,0bj2,{"name":"s","age":22}) //target 要拷贝到哪个对象上 // i 要执行拷 ...
- jQuery源码解析资源便签
最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...
- jquery源码解析:代码结构分析
本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94) 定义了一些变量和函数, jQuery = function() ...
- jQuery整体架构源码解析(转载)
jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...
- JQuery源码解析(一)
写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...
- jquery 源码解析
静态与实力方法共享设计 遍历方法 $(".a").each() //作为实例方法存在 $.each() //作为静态方法存在 Jquery源码 jQuery.prototype = ...
- jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...
- jQuery整体架构源码解析
最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
随机推荐
- 解决 Git 冲突的 14 个建议和工具
Git 非常善于合并代码.代码的合并在本地完成,快速而且灵活.正常情况下每次从不同分支合并内容时,冲突有可能会发生.通常解决冲突很简单,就如同知道(如何)选择(保留)重要的更改一样,而有时解决冲突则需 ...
- Swift类型转换
关于「类型转换」(Type Casting),<The Swift Programming Language>描述如下: Type casting is a way to check th ...
- js 异步问题
如果发现前端的异步请求,network有发送成功而且有返回值,但是没有进前端的callback成功回掉函数内,这时候就需要检查是不是配置文件做了语法限制,只能返回某些数据格式,不能返回某些数据格式. ...
- C++之PIMPL模式
1 PIMPL解释 PIMPL(Private Implementation 或 Pointer to Implementation)是通过一个私有的成员指针,将指针所指向的类的内部实现数据进行隐藏. ...
- Win32环境下代码注入与API钩子的实现
本文详细的介绍了在Visual Studio(以下简称VS)下实现API钩子的编程方法,阅读本文需要基础:有操作系统的基本知识(进程管理,内存管理),会在VS下编写和调试Win32应用程序和动态链接库 ...
- Spark Streaming之四:Spark Streaming 与 Kafka 集成分析
前言 Spark Streaming 诞生于2013年,成为Spark平台上流式处理的解决方案,同时也给大家提供除Storm 以外的另一个选择.这篇内容主要介绍Spark Streaming 数据接收 ...
- CSS3:CSS 参考手册
ylbtech-CSS:CSS 参考手册 1.返回顶部 1. W3School 的 CSS 参考手册定期通过所有主流浏览器进行测试. CSS 属性 CSS 属性组: 动画 背景 边框和轮廓 盒(框) ...
- bzoj3832
拓扑排序+set 如果我们直接记录所有路径是不行的,那么我们要降低路径的数量,于是我们把最短路径转换到边上,这样我们就只有m条路径了. 先计算出f[i]和g[i]表示正反拓扑最长链,把所有g插到set ...
- Visual Studio 2017 本地调试 Chrome浏览器自动退出
在使用VS 2017(15..6 .15.7)对.NET Core MVC应用程序进行本地调试的时候,选择使用Chrome浏览器.但输入中文 就自动关闭Chrome浏览器,随后结束调试.但复制.粘贴中 ...
- 1.13-1.14 Hive Action
一.Hive Action 1.创建文件 [root@hadoop-senior oozie-apps]# pwd /opt/cdh-5.3.6/oozie-4.0.0-cdh5.3.6/oozie- ...