2013-09-23 48 views
36

我正在使用Angular框架編寫單頁面應用程序。我是新手。我讀過this guide來幫助我理解jQuery和Angular之間的根本區別,我希望儘可能地遵循這個指導,而不是使用jQuery。如何在不使用jQuery的情況下獲得元素的offset()。top值?

除了jQuery有助於解決瀏覽器的一些不兼容問題,並提供了一個有用的函數庫,如能夠從窗口頂部知道元素的頂部位置,如$('element').offset().top。沒有簡單的Javascript似乎能夠接近不重寫此功能,在這一點上,它不是更好的主意,使用jQuery或類似jQuery的庫?

具體來說,我想要做的是建立一個指令,修復一個元素的位置,一旦它的頂部滾動到窗口中的某個位置。這裏是什麼樣子:

directives.scrollfix = function() { 
    return { 
     restrict: 'C', 
     link: function (scope, element, $window) { 

      var $page = angular.element(window) 
      var $el = element[0] 
      var elScrollTopOriginal = $($el).offset().top - 40 

      $page.bind('scroll', function() { 

       var windowScrollTop = $page[0].pageYOffset 
       var elScrollTop  = $($el).offset().top 

       if (windowScrollTop > elScrollTop - 40) { 
        elScrollTopOriginal = elScrollTop - 40 
        element.css('position', 'fixed').css('top', '40px').css('margin-left', '3px'); 
       } 
       else if (windowScrollTop < elScrollTopOriginal) { 
        element.css('position', 'relative').css('top', '0').css('margin-left', '0'); 
       } 
      }) 

     } 
    } 
} 

如果有一個更好的方法來實現這一目標的角度說,我仍然只是沒有得到,我會很感激的建議。

+0

接受的解決方案沒有考慮當前滾動位置考慮進去,看到我的回答如下 – schellmax

回答

55

使用getBoundingClientRect如果$el是實際的DOM對象:

var top = $el.getBoundingClientRect().top; 

JSFiddle

小提琴將表明,這將得到jQuery的偏離相同的值頂部會給你

編輯:正如評論中所提到的,這不包含滾動內容,下面是代碼th在jQuery使用

https://github.com/jquery/jquery/blob/master/src/offset.js(2015年5月13日)

offset: function(options) { 
    //... 

    var docElem, win, rect, doc, 
     elem = this[ 0 ]; 

    if (!elem) { 
     return; 
    } 

    rect = elem.getBoundingClientRect(); 

    // Make sure element is not hidden (display: none) or disconnected 
    if (rect.width || rect.height || elem.getClientRects().length) { 
     doc = elem.ownerDocument; 
     win = getWindow(doc); 
     docElem = doc.documentElement; 

     return { 
      top: rect.top + win.pageYOffset - docElem.clientTop, 
      left: rect.left + win.pageXOffset - docElem.clientLeft 
     }; 
    } 
} 
+1

看起來像這樣的跨瀏覽器的兼容性是偉大的太。謝謝。 – saikofish

+4

請注意,這個解決方案沒有考慮到當前的滾動位置,請參閱我的回答下面的 – schellmax

+0

我發現了一個非常簡單的... – Darren

3

由Patrick埃文斯接受的解決方案沒有考慮滾動考慮。 我已經稍微改變了他的jsfiddle證明這一點:

CSS:添加一些隨機的高度,以確保我們得到了一些空間,以滾動

body{height:3000px;} 

JS:設置一些滾動位置

jQuery(window).scrollTop(100); 

因此現在報告的兩個值不同:http://jsfiddle.net/sNLMe/66/

更新2015年2月14日

有一個jqLit​​e等待的拉取請求,包括它自己的偏移方法(注意當前的滾動位置)。看看源代碼,以防你想自己實現它:https://github.com/angular/angular.js/pull/3799/files

+0

cvmlrobotics鏈接已死亡。 – user2602152

+0

@ user2602152感謝您的評論,我用最近發現的其他信息取代了無效鏈接。 – schellmax

10

看來你可以只使用道具方法角元素:

var top = $el.prop('offsetTop'); 

爲我工作。有沒有人知道這個缺點?

+0

當我使用element.prepend()將元素添加到DOM時; offsetTop&Left總是0.然而在元素檢查器中,它不是0. –

+0

offsetTop屬性僅返回相對於元素父級的偏移量(https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop),而不是整個文檔,比如jQuery的offset()(http://api.jquery.com/offset/)。 – gluecksmelodie

+0

在第一次通過摘要的函數查找$ el之後異步加載DOM元素的情況下,這有點兒困難。結合Darren提供的解決方案 - 我必須首先使用普通的JS querySelector,將它包裝在角元素中,然後才能調用prop。 – vars

42

這裏是一個函數,將做沒有jQuery的:

function getElementOffset(element) 
{ 
    var de = document.documentElement; 
    var box = element.getBoundingClientRect(); 
    var top = box.top + window.pageYOffset - de.clientTop; 
    var left = box.left + window.pageXOffset - de.clientLeft; 
    return { top: top, left: left }; 
} 
+0

重新發明輪子(順便說一句,不是通用的)肯定比使用「癌症」更好,是的,當然... – Regent

+14

@Regent不是每個人都想包括一個巨大的圖書館做一些事情否則可以用5行代碼完成。 – Wolverine

+0

例如,jquery-2.1.3.min.js(83KB)不是巨型文件。怎麼樣的項目(而不是_AngularJS_的)_jQuery_在很多地方使用?你是否建議編寫一個函數來使代碼(與DOM協同工作)更短?沒有很好的測試,有錯誤,沒有良好的交叉瀏覽?我明白,_jQuery_不應該在所有項目中使用,但通過侮辱_jQuery_您聲明它不應該在任何地方使用(順便提一句,這是錯誤的陳述),不是嗎? – Regent

相關問題