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 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...
随机推荐
- 关于Ajax实现的简单示例
一.代码示例 关于Ajax的基本概念(包括XMLHttpRequest对象及其相关方法属性)移步这里(w3school中文版)学习了解. <!doctype html> <html ...
- ICE协议下NAT穿越的实现(STUN&TURN)
正文: 一. 首先来简单讲讲什么是NAT? 原来这是因为IPV4引起的,我们上网很可能会处在一个NAT设备(无线路由器之类)之后.NAT设备会在IP封包通过设备时修改源/目的IP地址. 对于家用路由器 ...
- 运行swoole_server方法
运行 php 文件 server.php 运行结果是如下: 只是服务器开启了 如果想看客户端连接的情况 可以测试一下 从新连接一个连接 用命令 方式 telnet 127.0.0.1 9501 这个9 ...
- opencv3.4.0 安装过程中出现的问题
重新安装opencv3.4.0 参考安装博客: opencv 安装版本测试:pkg-config --modversion opencv https://blog.csdn.net/cocoaqin/ ...
- C++之面向对象初探----对象管理模型(关键是this指针)
前言 c++对象模型可以概括为以下2部分 1.语言中直接支持面向对象程序员设计部分,主要涉及如构造函数.析构函数.虚函数.继承(单继承.多继承.虚继承).多态等待. 2.对于各种支持的底层实现机制 在 ...
- 【Boost】boost库asio详解3——io_service作为work pool
无论如何使用,都能感觉到使用boost.asio实现服务器,不仅是一件非常轻松的事,而且代码很漂亮,逻辑也相当清晰,这点上很不同于ACE.使用io_service作为处理工作的work pool,可以 ...
- OA系统
当用户登录时,根据用户名让他去查找用户的ID,编号,角色,权限,部门信息,等信息查找出来,用户表和角色表是一个一对多的关系,角色和权限也是一个一对多的关系,所以总共加起来有五张表,获取权限是通过用户名 ...
- redis 操作使用
/*1.Connection*/ $redis = new Redis(); $redis->connect('127.0.0.1',6379,1);//短链接,本地host,端口为6379,超 ...
- Redis的小白应用
在window下测试学习redis 步骤: 1.先下载安装 redis,(conf文件制定配置文件(redis-server.exe redis.conf ),若不指定则默认), 基本上我是直接点击 ...
- URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)
URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs) 有时候在IDEA中配置spring文件 ...