2013-09-23 31 views
36

Tôi đang lập trình một ứng dụng một trang bằng khung công tác Góc. Tôi mới làm quen với nó. Tôi đã đọc this guide để giúp tôi hiểu những khác biệt cơ bản giữa jQuery và Angular và tôi muốn làm theo hướng dẫn này càng nhiều càng tốt và KHÔNG sử dụng jQuery.Làm thế nào để có được giá trị trên() của một phần tử không sử dụng jQuery?

Ngoại trừ jQuery giúp giải quyết một số tính không tương thích của trình duyệt và cung cấp thư viện chức năng hữu ích, như có thể biết vị trí trên cùng của phần tử từ đầu cửa sổ, như trong $('element').offset().top. Không có Javascript đơn giản dường như có thể đến gần mà không cần viết lại chức năng này, tại thời điểm nào không phải là nó một ý tưởng tốt hơn để sử dụng thư viện jQuery hoặc jQuery?

Cụ thể, những gì tôi đang cố gắng là thiết lập một chỉ thị sửa một phần tử tại vị trí khi đầu nó được cuộn đến một vị trí nhất định trong cửa sổ. Dưới đây là hình thức:

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'); 
       } 
      }) 

     } 
    } 
} 

Nếu có cách nào tốt hơn để đạt được điều này trong góc mà tôi vẫn chưa nhận được, tôi xin đánh giá cao lời khuyên.

+0

giải pháp được chấp nhận không lấy vị trí cuộn hiện tại vào tài khoản, xem câu trả lời của tôi dưới đây – schellmax

Trả lời

55

sử dụng getBoundingClientRect nếu $el là đối tượng DOM thực tế:

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

JSFiddle

Fiddle sẽ hiển thị rằng điều này sẽ nhận được giá trị tương tự mà jquery bù đắp hàng đầu sẽ cung cấp cho bạn

Chỉnh sửa: như đã đề cập trong nhận xét, điều này không tính đến nội dung được cuộn, bên dưới là mã thứ tại jQuery sử dụng

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

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

Hình như khả năng tương thích trình duyệt chéo về vấn đề này là rất tốt quá. Cảm ơn. – saikofish

+4

lưu ý rằng giải pháp này không giải thích cho vị trí di chuyển hiện tại, hãy xem câu trả lời của tôi bên dưới – schellmax

+0

Tôi đã tìm thấy một giải pháp đơn giản bên dưới ... – Darren

3

giải pháp chấp nhận bởi Patrick Evans không mất di chuyển vào tài khoản. tôi đã hơi thay đổi jsfiddle của mình để chứng minh điều này:

css: thêm một số chiều cao ngẫu nhiên để đảm bảo chúng tôi có một số không gian để di chuyển

body{height:3000px;} 

js: thiết lập một số vị trí cuộn

jQuery(window).scrollTop(100); 

kết quả là hai giá trị được báo cáo khác nhau bây giờ: http://jsfiddle.net/sNLMe/66/

CẬP NHẬT 14 tháng 2 năm 2015

có yêu cầu kéo để chờ jqLite, bao gồm phương thức bù của riêng nó (chú ý đến vị trí cuộn hiện tại). hãy xem nguồn trong trường hợp bạn muốn tự mình triển khai: https://github.com/angular/angular.js/pull/3799/files

+0

Liên kết cvmlrobotics đã chết. – user2602152

+0

@ user2602152 cảm ơn nhận xét của bạn, tôi đã thay thế liên kết chết bằng thông tin bổ sung mà tôi đã tìm thấy gần đây. – schellmax

10

Có vẻ bạn chỉ có thể sử dụng phương pháp prop trên các yếu tố góc:

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

trình cho tôi. Có ai biết bất kỳ nhược điểm này?

+0

Khi tôi thêm phần tử vào DOM với phần tử elementreprepend(); offsetTop & Left luôn là 0. Tuy nhiên trong thanh tra phần tử, nó không phải là 0. –

+0

Thuộc tính offsetTop chỉ trả về giá trị offset tương ứng với phụ huynh của phần tử (https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop), và không cho toàn bộ tài liệu như offset của jQuery() (http://api.jquery.com/offset/). – gluecksmelodie

+0

Đó là một chút của một rigamarole trong trường hợp phần tử DOM của bạn được tải không đồng bộ sau khi hàm tìm kiếm $ el trên lần truyền đầu tiên thông qua thông báo. Kết hợp với giải pháp được cung cấp bởi Darren - tôi đã phải sử dụng đầu tiên JS querySelector đồng bằng, bọc nó trong phần tử góc và sau đó đã có thể gọi prop. – vars

42

Đây là một chức năng mà sẽ làm điều đó mà không cần 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

Tái phát minh bánh xe (không phải là phổ quát, nhân tiện) chắc chắn tốt hơn sau đó sử dụng "ung thư", vâng, chắc chắn ... – Regent

+14

@Regent Không phải ai cũng muốn đưa một thư viện khổng lồ để làm điều gì đó có thể được thực hiện trong 5 dòng mã. – Wolverine

+0

Ví dụ: jquery-2.1.3.min.js (83KB) không phải là tệp khổng lồ. Còn dự án (không phải là _AngularJS_), nơi _jQuery_ được sử dụng ở nhiều nơi? Bạn có đề nghị viết một hàm của bạn để làm cho mã (làm việc với DOM) ngắn hơn không? Không được kiểm tra tốt, có lỗi, không có trình duyệt chéo tốt? Tôi hiểu rằng _jQuery_ không nên được sử dụng trong tất cả các dự án, nhưng bằng cách xúc phạm _jQuery_ bạn nói rằng nó không nên được sử dụng ở bất cứ nơi nào (và đây là tuyên bố sai, nhân tiện), phải không? – Regent

Các vấn đề liên quan