成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

jQuery源碼解析之position()

sunsmell / 2208人閱讀

摘要:注意的本質(zhì)是的解析整體上看,是一個(gè)語句由于的元素,是相對(duì)于瀏覽器窗口進(jìn)行定位的,所以它的偏移就是,即獲取某個(gè)元素相對(duì)于視窗的位置。注意的本質(zhì)是的完

position()
作用:
返回被選元素相對(duì)于父元素(parent)的偏移坐標(biāo)

使用:
直接調(diào)用$().position()即可,該方法沒有 arguments(參數(shù)對(duì)象)



這是divTwo

源碼:

  // 返回被選元素相對(duì)于父元素(parent)的偏移坐標(biāo)
    // 可以理解成被選元素設(shè)置為absolute,
    // 然后設(shè)置left、top的值就是相對(duì)于父元素的偏移坐標(biāo)
    // 源碼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的元素,是相對(duì)于瀏覽器窗口進(jìn)行定位的,
      // 所以它的偏移就是getBoundingClientRect(),即獲取某個(gè)元素相對(duì)于視窗的位置
      if ( jQuery.css( elem, "position" ) === "fixed" ) {

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

      }
      // 除去position是fixed的情況
      else {
        // 獲取被選元素相對(duì)于文檔(document)的偏移坐標(biāo)
        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;
        //定位目標(biāo)元素的父元素(position不為static的元素)
        offsetParent = elem.offsetParent || doc.documentElement;
        // 如果父元素是/的話,將父元素重新定位為它們的父元素
        // body的父元素是html,html的父元素是document
        while ( offsetParent &&
        ( offsetParent === doc.body || offsetParent === doc.documentElement ) &&
        jQuery.css( offsetParent, "position" ) === "static" ) {

          offsetParent = offsetParent.parentNode;
        }
        // 如果定位父元素存在,并且不等于目標(biāo)元素,并且定位元素類型是 "元素類型"
        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 表示返回?cái)?shù)字,而不帶單位 px
          parentOffset.top += jQuery.css( offsetParent, "borderTopWidth", true );
          parentOffset.left += jQuery.css( offsetParent, "borderLeftWidth", true );
        }
      }

      // Subtract parent offsets and element margins
      // 可以看出,$().position()的本質(zhì)是目標(biāo)元素的offset()減去父元素的offset(),同時(shí)還要算上目標(biāo)元素的margin,因?yàn)楹凶幽P停P(guān)鍵)。
      //(注意:offset()的本質(zhì)是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 )
      };
    },

解析:
整體上看,是一個(gè) 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的元素,是相對(duì)于瀏覽器窗口進(jìn)行定位的,所以它的偏移就是getBoundingClientRect(),即獲取某個(gè)元素相對(duì)于視窗的位置。

注意:
① getBoundingClientRect() 計(jì)算的是目標(biāo)元素的border的位置(左上角),是不包括margin的
② 如果不加上margin的話(代碼是通過減去,來算上margin的),是不準(zhǔn)確的,看下圖

所以源碼最后會(huì):

- jQuery.css( elem, "marginTop", true )
- jQuery.css( elem, "marginLeft", true )

(2)jQuery.css( elem, "width", true )
true的作用是返回該屬性的數(shù)字,而不帶單位 px

(3)定位父元素存在,并且不等于目標(biāo)元素,并且定位元素類型是 "元素類型"的話

if ( offsetParent && offsetParent !== elem && offsetParent.nodeType === 1 )

是要減去border屬性的值的

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

為啥?舉個(gè)例子:

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

設(shè)置 borderLeftWidth 為 8 像素

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

可以看到getBoundingClientRect()指定坐標(biāo)是到border上的,這是不準(zhǔn)確的,因?yàn)樵诶锩娴淖釉氐奈恢靡矔?huì)受父元素的border影響,所以父元素的坐標(biāo)需要越過border

綜上:
可以看出,$().position()的本質(zhì)是目標(biāo)元素的 offset() 減去父元素的 offset(),同時(shí)還要算上目標(biāo)元素的 margin,算上父元素的border。
(注意:offset()的本質(zhì)是getBoundingClientRect()的top、left + pageYOffset、pageXOffset)

Github:
https://github.com/AttackXiao...

(完)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104106.html

相關(guān)文章

  • jQuery源碼解析offset()

    摘要:也就是說的本質(zhì)為參數(shù)的屬性減去對(duì)應(yīng)的默認(rèn)屬性加上上的對(duì)應(yīng)屬性。所以的本質(zhì)即相對(duì)于,對(duì)其,進(jìn)行操作,而不是像那樣相對(duì)于左上角原點(diǎn)進(jìn)行操作這樣就需要先減去中的的值了。 showImg(https://upload-images.jianshu.io/upload_images/5518628-d5ec366642ca36ab.jpg?imageMogr2/auto-orient/strip...

    keke 評(píng)論0 收藏0
  • jQuery源碼解析$().animate()(上)

    摘要:前言需要先看源碼解析之和一舉例的寬度先變成,再變成,最后變成這是在異步調(diào)用中,進(jìn)行同步調(diào)用動(dòng)畫是異步的就是連續(xù)調(diào)用二作用通過樣式將元素從一個(gè)狀態(tài)改變?yōu)榱硪粋€(gè)狀態(tài)源碼之前有說過是的方法源碼行是否是空對(duì)象,方法執(zhí)行單個(gè)動(dòng)畫的封裝的本質(zhì)是執(zhí)行 showImg(https://segmentfault.com/img/remote/1460000019594521); 前言:需要先看 jQue...

    Batkid 評(píng)論0 收藏0
  • jQuery源碼解析clone()

    摘要:五作用的關(guān)鍵方法,用來從目標(biāo)節(jié)點(diǎn)克隆數(shù)據(jù)添加事件給克隆的元素注意采用數(shù)據(jù)分離的方法來保存上的事件和數(shù)據(jù),利用標(biāo)記每個(gè)元素,然后在內(nèi)存上,將每個(gè)元素相關(guān)的數(shù)據(jù)放到內(nèi)存中,然后在和內(nèi)存的數(shù)據(jù)之間建立映射。 showImg(https://segmentfault.com/img/remote/1460000018991125); 前言:這篇講完后,jQuery的文檔處理就告一段落了,有空我...

    coolpail 評(píng)論0 收藏0
  • jQuery源碼解析jQuery.event.dispatch()

    摘要:一起源方法最終是用綁定事件的而方法正是等于二作用觸發(fā)綁定的事件的處理程序源碼源碼行即原生觸發(fā)事件的處理程序修正對(duì)象獲取事件的處理程序集合,結(jié)構(gòu)如下從數(shù)據(jù)緩存中獲取事件處理集合即目標(biāo)元素委托目標(biāo)這段代碼壓根不會(huì)執(zhí)行,因?yàn)槿炙阉鳑]找到結(jié)構(gòu) showImg(https://segmentfault.com/img/remote/1460000019464031); 一、起源jQuery.e...

    GraphQuery 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<