position()
作用:
返回被选元素相对于父元素(parent)的偏移坐标

使用:
直接调用$().position()即可,该方法没有 arguments(参数对象)

<body><script src="jQuery.js"></script><p id="pTwo">这是divTwo</p><script>  $("#pTwo").position() //{top: 0, left: 8}</script></body>复制代码

源码:

  // 返回被选元素相对于父元素(parent)的偏移坐标    // 可以理解成被选元素设置为absolute,    // 然后设置left、top的值就是相对于父元素的偏移坐标    // 源码10571行    // position() relates an element's margin box to its offset parent's padding box    // This corresponds to the behavior of CSS absolute positioning    position: function() {      // 如果DOM元素不存在,直接返回      if ( !this[ 0 ] ) {        return;      }

      var offsetParent, offset, doc,        elem = this[ 0 ],        parentOffset = { top: 0, left: 0 };

      // position:fixed elements are offset from the viewport, which itself always has zero offset      // position:fixed的元素,是相对于浏览器窗口进行定位的,      // 所以它的偏移就是getBoundingClientRect(),即获取某个元素相对于视窗的位置      if ( jQuery.css( elem, "position" ) === "fixed" ) {

        // Assume position:fixed implies availability of getBoundingClientRect        offset = elem.getBoundingClientRect();

      }      // 除去position是fixed的情况      else {        // 获取被选元素相对于文档(document)的偏移坐标        offset = this.offset();

        // Account for the *real* offset parent, which can be the document or its root element        // when a statically positioned element is identified        doc = elem.ownerDocument;        //定位目标元素的父元素(position不为static的元素)        offsetParent = elem.offsetParent || doc.documentElement;        // 如果父元素是<body>/<html>的话,将父元素重新定位为它们的父元素        // body的父元素是html,html的父元素是document        while ( offsetParent &&        ( offsetParent === doc.body || offsetParent === doc.documentElement ) &&        jQuery.css( offsetParent, "position" ) === "static" ) {

          offsetParent = offsetParent.parentNode;        }        // 如果定位父元素存在,并且不等于目标元素,并且定位元素类型是 "元素类型"        if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 ) {

          // Incorporate borders into its offset, since they are outside its content origin          parentOffset = jQuery( offsetParent ).offset();          // 这两行代码的意思是父元素的offset()要从padding算起,不包括border          // 所以需要去掉border          // jQuery.css( element, "borderTopWidth", true )的 true 表示返回数字,而不带单位 px          parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );          parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );        }      }

      // Subtract parent offsets and element margins      // 可以看出,$().position()的本质是目标元素的offset()减去父元素的offset(),同时还要算上目标元素的margin,因为盒子模型(关键)。      //(注意:offset()的本质是getBoundingClientRect()的top、left + pageYOffset、pageXOffset)      return {        top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),        left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )      };    },复制代码

解析:
整体上看,是一个 if(...fixed) { } esle { } 语句
(1)if ( jQuery.css( elem, "position" ) === "fixed" )

if ( jQuery.css( elem, "position" ) === "fixed" ) {        // Assume position:fixed implies availability of getBoundingClientRect        offset = elem.getBoundingClientRect();}return {        top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),        left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )      };复制代码

由于position:fixed的元素,是相对于浏览器窗口进行定位的,所以它的偏移就是getBoundingClientRect(),即获取某个元素相对于视窗的位置。

注意:
① getBoundingClientRect() 计算的是目标元素的border的位置(左上角),是不包括margin的
② 如果不加上margin的话(代码是通过减去,来算上margin的),是不准确的,看下图

所以源码最后会:

- jQuery.css( elem, "marginTop", true )- jQuery.css( elem, "marginLeft", true )复制代码

(2)jQuery.css( elem, "width", true )
true的作用是返回该属性的数字,而不带单位 px

(3)定位父元素存在,并且不等于目标元素,并且定位元素类型是 "元素类型"的话

if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 )复制代码

是要减去border属性的值的

parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );复制代码

为啥?举个例子:

let p=document.querySelector("#pTwo")console.log(p.getBoundingClientRect(),'pTwo11'); //x:8,y:16复制代码

设置 borderLeftWidth 为 8 像素

let p=document.querySelector("#pTwo")p.style.borderLeftWidth='8px'console.log(p.getBoundingClientRect(),'pTwo11'); //x:8,y:16复制代码

可以看到getBoundingClientRect()指定坐标是到border上的,这是不准确的,因为在里面的子元素的位置也会受父元素的border影响,所以父元素的坐标需要越过border

综上:
可以看出,$().position()的本质是目标元素的 offset() 减去父元素的 offset(),同时还要算上目标元素的 margin,算上父元素的border。
(注意:offset()的本质是getBoundingClientRect()的top、left + pageYOffset、pageXOffset)

Github:
github.com/AttackXiaoJ…


(完)

jQuery源码解析之position()相关推荐

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

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

  2. JQuery 源码解析资料

    2019独角兽企业重金招聘Python工程师标准>>> jQuery源码分析系列目录 jQuery源码解读-理解架构 jQuery源码解析(架构与依赖模块) jQuery v1.10 ...

  3. jQuery源码解析(架构与依赖模块)

    jQuery设计理念 引用百科的介绍: jQuery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1. ...

  4. jQuery源码解析(架构与依赖模块)第一章 理解架构

    1-1 jQuery设计理念 引用百科的介绍: jQuery是继prototype之后又一个优秀的Javascript框架.它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, F ...

  5. jquery源码解析:jQuery数据缓存机制详解2

    上一课主要讲了jQuery中的缓存机制Data构造方法的源码解析,这一课主要讲jQuery是如何利用Data对象实现有关缓存机制的静态方法和实例方法的.我们接下来,来看这几个静态方法和实例方法的源码解 ...

  6. jQuery 源码解析一:jQuery 类库整体架构设计解析

    如果是做 web 的话,相信都要对 Dom 进行增删查改,那大家都或多或少接触到过 jQuery 类库,其最大特色就是强大的选择器,让开发者脱离原生 JS 一大堆 getElementById.get ...

  7. jQuery源码解析之on事件绑定

    本文采用的jQuery源码为jquery-3.2.1.js jquery的on方法用来在选定的元素上绑定一个或多个事件处理函数. 当参数selector存在时,通常会用来对已经存在的元素或将来即将添加 ...

  8. 浅谈jquery源码解析

    本文主要是针对jquery  v3.x版本来描述的,将从以下几个方面谈谈我对jquery的认识, 总体架构 $与$.fn jQuery.fn.init  (重要) jQuery.extend  与jQ ...

  9. jQuery源码解析之offset()

    一.offset() 作用: 返回被选元素相对于文档(document)的偏移坐标 二.三种情况使用: 1.$().offset() <body><script src=" ...

最新文章

  1. 蔚来李斌:自动驾驶好处是解放生产力、保障生命安全
  2. 四种ASP网页跳转代码
  3. jmeter 最大时间长_长连接和短连接区别和优缺点
  4. canvas画布 带箭头的虚线_娇小女生只能走可爱风?No!带你解锁别样的高级穿搭法则...
  5. 《DSP using MATLAB》示例Example7.20
  6. LeetCode 1150. 检查一个数是否在数组中占绝大多数(二分查找)
  7. Gartner最新发布:影响2022年基础设施和运营重大趋势
  8. woff字体MIME类型配置
  9. 【python】 类、对象的练习题
  10. pyqt5开发环境配置
  11. Android NDK开发1——开发流程+依赖外部so+生成自实现so+静态注册JNI+动态注册JNI
  12. 成의 時運의 圖像 正易八卦圖
  13. idb 怎么回复mysql_mysql中的.idb文件 怎么正常显示
  14. 6个超实用网站,让你工作时长减半。
  15. 【数据库内核】数据库核心技术演进之路
  16. Ansible剧本示例
  17. linux 怎么看节点核数,Linux怎么查看CPU核数?-linux运维
  18. textpad java sdk_如何防止TextPad在运行Java时创建临时批处理文件?
  19. 100.8元该怎么花,笨拙的人从来不会思考这个问题
  20. 三维坐标向任意平面的正平行投影

热门文章

  1. static和不完全类型的一个例子
  2. 6-堆排序C实现(递增递减的简单转换,可优化(41行提示))
  3. ROS学习笔记-ROS语音识别与语音输出[2]
  4. [BUUCTF-pwn]——pwn1_sctf_2016
  5. python怎么定义文档的行数_python删除文本中行数标签的方法
  6. python 多维数组轴_python – numpy通过任意轴重塑多维数组
  7. angular跳转指定页面_通过 angular CDK 实现页面元素拖放
  8. stop() 和 suspend() 方法为何不推荐使用
  9. Oralce中日期格式
  10. 2分钟学会ajax 入门ajax必备