首先是原型上的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()源码解析的更多相关文章

  1. jquery 部分函数源码解析

    JSON.stringify源码(在看extend文档的时候看到) var object1 = { apple: 0, banana: {weight: 52, price: 100}, cherry ...

  2. jquery extend源码解析

    $.extend(obj1,0bj2,{"name":"s","age":22}) //target 要拷贝到哪个对象上 // i 要执行拷 ...

  3. jQuery源码解析资源便签

    最近开始解读jQuery源码,下面的链接都是搜过来的,当然妙味课堂 有相关的一系列视频,长达100多期,就像一只蜗牛慢慢爬, 至少品读三个框架,以后可以打打怪,自己造造轮子. 完全理解jQuery源代 ...

  4. jquery源码解析:代码结构分析

    本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94)     定义了一些变量和函数,   jQuery = function() ...

  5. jQuery整体架构源码解析(转载)

    jQuery整体架构源码解析 最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性, ...

  6. JQuery源码解析(一)

    写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...

  7. jquery 源码解析

    静态与实力方法共享设计 遍历方法 $(".a").each() //作为实例方法存在 $.each() //作为静态方法存在 Jquery源码 jQuery.prototype = ...

  8. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  9. jQuery整体架构源码解析

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

随机推荐

  1. the art of seo(chapter six)

    Developing an SEO-Friendly Website ***Making Your Site Accessible to Search Engines***1.Indexable Co ...

  2. Java 发送Get和Post请求

    package com.htpt.superviseServices.dm.util; import java.io.BufferedReader; import java.io.IOExceptio ...

  3. codeforces 702C C. Cellular Network(水题)

    题目链接: C. Cellular Network time limit per test 3 seconds memory limit per test 256 megabytes input st ...

  4. Linux GCC常用命令学习

    1简介 GCC 的意思也只是 GNU C Compiler 而已.经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言:它现在还支持 Ada 语言.C++ 语言.Java 语言.Objective ...

  5. kali本機安裝openvas的血淚史復盤

    安裝openvas的血淚史 因爲學習的需要,需要裝openvas,但是在虛擬機裏面,無論怎麼更新跟新源,總是會有問題,一氣之下,便不用虛擬機了,將自己的物理機刷成了kali機,從此便進了一個大坑. 安 ...

  6. TX2 刷机过程

    1.拿到板子,上电 (1)输入 ls (2)进入NVIDIA-INSTALLER/ (3)再sudo ./installer.sh 账户和密码都是:nvidia (4)sudo reboot 参考博客 ...

  7. Oracle数据库当前连接数、最大连接数的查询与设置

    在开发过程中Oracle数据库有时候连得上,有时候又连不上,提示如下异常“ORA-12519: TNS:no appropriate service handler found 解决”,可能是数据库上 ...

  8. spring : springmvc常用注解标签详解(转)

    新的项目,新的学习,好久没用这些注解了,同时在学习使用shiro ,lucene 等等.在网上找了些博文,感谢作者的总结和分享. 欢迎交流,言归正传: 1.@Controller 在SpringMVC ...

  9. mina框架之---服务端NioSocketAcceptor的学习

    接上一讲对mina的简单应用和对mina服务端和客户端中几个重要的技术知识点的理解后,今天着重对mina服务端的NioSocketAcceptor 进行学习. 说这个玩意之前,先整体上看一下在mina ...

  10. 怎么在Ubuntu下设置程序的快捷键

    参考 http://jingyan.baidu.com/article/1e5468f97f9e75484861b773.html 我的系统是 64bit Ubuntu14.04 我设置了 gedit ...