angular.element vs document.getEuityById hoặc bộ chọn jQuery với điều khiển spin (bận)


157

Tôi đang sử dụng phiên bản "Angularised" của điều khiển Spin, như được ghi lại ở đây: http://blog.xvitcoder.com/adding-a-weel-proTHER-indicator-to-your-angularjs-application/

Một trong những điều tôi không thích về giải pháp được hiển thị là việc sử dụng jQuery trong dịch vụ gắn hiệu quả điều khiển quay với phần tử DOM. Tôi muốn sử dụng các cấu trúc góc để truy cập phần tử. Tôi cũng muốn tránh "mã hóa cứng" id của phần tử mà spinner cần đính kèm trong dịch vụ và thay vào đó sử dụng một lệnh đặt id trong dịch vụ (singleton) để những người dùng dịch vụ khác hoặc bản thân dịch vụ không cần biết điều đó.

Tôi đang vật lộn với những gì angular.element mang lại cho chúng ta so với những gì document.getEuityById trên cùng một id phần tử mang lại cho chúng ta. ví dụ. Những công việc này:

  var target = document.getElementById('appBusyIndicator');

Không ai trong số này làm:

  var target = angular.element('#appBusyIndicator');
  var target = angular.element('appBusyIndicator');

Tôi rõ ràng đang làm một cái gì đó khá rõ ràng sai! Có ai giúp được không?

Giả sử tôi có thể làm việc ở trên, tôi gặp vấn đề tương tự với việc cố gắng thay thế quyền truy cập jQuery vào phần tử: ví dụ: $(target).fadeIn('fast'); hoạt động angular.element('#appBusyIndicator').fadeIn('fast')hoặc angular.element('appBusyIndicator').fadeIn('fast')không

Ai đó có thể chỉ cho tôi một ví dụ hay về tài liệu làm rõ việc sử dụng "phần tử" Angular so với phần tử DOM không? Angular rõ ràng "bao bọc" phần tử bằng các thuộc tính, phương thức riêng của nó, v.v. nhưng thường rất khó để có được giá trị ban đầu. Ví dụ: nếu tôi có một <input type='number'>trường và tôi muốn truy cập nội dung gốc có thể nhìn thấy trong ui khi người dùng gõ "-" (không có dấu ngoặc kép) thì tôi không nhận được gì, có lẽ vì "type = number" có nghĩa là Angular đang từ chối đầu vào mặc dù nó hiển thị trong giao diện người dùng và tôi muốn xem nó để tôi có thể kiểm tra và xóa nó đi.

Bất kỳ con trỏ / câu trả lời đánh giá cao.

Cảm ơn.


5
angular.element là một đối tượng jQlite hoặc đối tượng jQuery nếu bạn đang tải jQuery.
Neil

Câu trả lời:


226

có thể hoạt động như thế:

var myElement = angular.element( document.querySelector( '#some-id' ) );

Bạn kết thúc cuộc gọi Document.querySelector()Javascript gốc vào angular.element()cuộc gọi. Vì vậy, bạn luôn nhận được phần tử trong một đối tượng jqLite hoặc jQuery , tùy thuộc vào việc jQuerycó sẵn / được tải hay không .

Tài liệu chính thức cho angular.element:

Nếu jQuery có sẵn, angular.elementlà một bí danh cho jQueryhàm. Nếu jQuery không có sẵn, angular.elementcác đại biểu cho tập hợp con có sẵn của AngularjQuery , được gọi là "jQuery lite" hoặc jqLite .

Tất cả các tham chiếu phần tử Angularluôn được gói bằng jQuery hoặc jqLite(chẳng hạn như đối số phần tử trong một lệnh biên dịch hoặc hàm liên kết). Chúng không bao giờ là DOMtài liệu tham khảo thô .

Trong trường hợp bạn tự hỏi tại sao để sử dụng document.querySelector(), xin vui lòng đọc câu trả lời này .


41
Bất kỳ lý do nào người ta sẽ thích document.querySelector ('# ...') chỉ đơn giản là sử dụng document.getEuityById ()?
Kato

4
Bạn cũng có thể làm điều này trên một phần tử góc: var elDivParent = angular.element (elem [0] .querySelector ('# an-id'));, elem là một phần tử góc. Bằng cách này bạn có thể tìm kiếm bên trong một yếu tố. Hữu ích cho các bài kiểm tra đơn vị.
bao gồm

4
@Kato Thêm thông tin trong câu trả lời này . Mong rằng sẽ giúp.
kaiser

làm việc với API Google Maps và điều này đã hoạt động : var autocomplete = new google.maps.places.Autocomplete( $document[0].querySelector('#address'), { types: ['geocode'], componentRestrictions: {country: 'us'} } );. Cảm ơn vì mẹo @kaiser. Vì một số lý do, api bản đồ phàn nàn rằng những gì tôi đã vượt qua trong thông số đầu tiên không phải là đầu vào khi tôi sử dụng angular.element(document.querySelector('#address')), nhưng tất cả đều kết thúc tốt đẹp.
nymo

49

Bạn nên đọc các tài liệu phần tử góc nếu bạn chưa có, vì vậy bạn có thể hiểu những gì được jqLite hỗ trợ và những gì không -jqlite là một tập hợp con của jquery được xây dựng thành góc.

Các bộ chọn đó sẽ không hoạt động với jqLite một mình, vì các bộ chọn theo id không được hỗ trợ.

  var target = angular.element('#appBusyIndicator');
  var target = angular.element('appBusyIndicator');

Vì vậy :

  • bạn sử dụng jqLite một mình, hạn chế hơn jquery, nhưng đủ trong hầu hết các tình huống.
  • hoặc bạn bao gồm lib lib đầy đủ trong ứng dụng của bạn và sử dụng nó như jquery bình thường, ở những nơi bạn thực sự cần jquery.

Chỉnh sửa: Lưu ý rằng jQuery nên được tải trước angularJS để được ưu tiên hơn jqLite:

Real jQuery luôn được ưu tiên hơn jqLite, miễn là nó được tải trước khi sự kiện DOMContentLoaded được kích hoạt.

Edit2: Tôi đã bỏ lỡ phần thứ hai của câu hỏi trước:

Vấn đề với <input type="number">, tôi nghĩ đó không phải là một vấn đề góc cạnh, đó là hành vi dự định của phần tử số html5 gốc .

Nó sẽ không trả về giá trị không phải là số ngay cả khi bạn cố truy xuất nó bằng jquery's .val()hoặc với .valuethuộc tính thô .


2
Chúng tôi có thư viện jQuery đầy đủ - nếu không kịch bản $ của tôi được giải thích ở trên sẽ không hoạt động. Câu hỏi của tôi là xung quanh lý do tại sao $ hoạt động nhưng angular.element không - mặc dù có sẵn jQuery đầy đủ.
irascian

1
Bạn có bao gồm jQuery trước hoặc sau angular.js không? Nó nên được bao gồm trước khi góc. Selectors bởi id làm việc với jQuery có sẵn: jsbin.com/ohumiy/1/edit
Garst

1
Họ đang làm việc trong một chỉ thị khác (tức là angular.element để truy cập một cái gì đó theo id). Vấn đề dường như là cách điều khiển này hoạt động bằng cách tự gắn vào phần tử đó, mặc dù tôi không hiểu tại sao cùng một jQuery tương tự nên hoạt động. Sử dụng trực tiếp jQuery chỉ thị của tôi ĐÃ có thẻ đóng - thẻ tự đóng không hoạt động (không có lỗi chỉ là màn hình trống) khiến tôi nghi ngờ điều khiển.
irascian

2
Ở điểm thứ 2 của tôi cũng có một cái gì đó như view $ value có thể được sử dụng để truy xuất nội dung của một phần tử nhưng trong trường hợp kiểu nhập = số mà người dùng có đầu vào "-" thì đây là sản phẩm trống. Tôi muốn một thuộc tính giống như $ rawInputValue trên phần tử để xem nội dung TRƯỚC KHI Angular đã bước vào vì "-" vẫn còn trong UI mặc dù tôi không có quyền truy cập theo chương trình trong chỉ thị của mình.
irascian

27
var target = document.getElementById('appBusyIndicator');

bằng

var target = $document[0].getElementById('appBusyIndicator');

1
Tốt hơn là sử dụng ví dụ thứ hai để đảm bảo rằng các phụ thuộc của bạn rõ ràng và có thể bị chế giễu, phải không?
Lu-ca

nó nên như vậy, nhưng tôi đoán Trong 2+ góc cạnh, chúng ta chỉ dựa vào nhiều hơn về các tính năng bản thảo. Không còn phải lo lắng về những điều này :)
Dasun

17

Tôi không nghĩ rằng đó là cách đúng đắn để sử dụng góc cạnh. Nếu một phương thức khung không tồn tại, đừng tạo nó! Điều này có nghĩa là khung (ở đây góc) không hoạt động theo cách này.

Với góc cạnh, bạn không nên thao tác DOM như thế này (cách jquery), mà sử dụng trình trợ giúp góc như

<div ng-show="isLoading" class="loader"></div>

Hoặc tạo chỉ thị của riêng bạn (thành phần DOM của riêng bạn) để có toàn quyền kiểm soát nó.

BTW, bạn có thể xem tại đây http://caniuse.com/#search=queryselector querySelector được hỗ trợ tốt và do đó có thể được sử dụng một cách an toàn.


2
Bạn hoàn toàn đúng. 90% + trong số các trường hợp mà tôi nghĩ rằng tôi cần phải thao tác thủ công DOM, cuối cùng tôi đã tái cấu trúc mã để loại bỏ sự cần thiết và cuối cùng, mã này sạch hơn rất nhiều.
Stephen Chung

17

Nếu ai đó sử dụng gulp, nó sẽ báo lỗi nếu chúng tôi sử dụng document.getElementById()và nó đề nghị sử dụng $document.getElementById()nhưng nó không hoạt động.

Sử dụng -

$document[0].getElementById('id')

Tại sao góc tiêm một mảng ở đây?
Peter

16

Bạn có thể truy cập các phần tử bằng cách sử dụng tài liệu $ (tài liệu $ cần được chèn)

var target = $document('#appBusyIndicator');
var target = $document('appBusyIndicator');

hoặc với phần tử góc, các phần tử được chỉ định có thể được truy cập dưới dạng:

var targets = angular.element(document).find('div'); //array of all div
var targets = angular.element(document).find('p');
var target = angular.element(document).find('#appBusyIndicator');

1
find () - Giới hạn tra cứu theo tên thẻ
RJV

angular.element (tài liệu) .find ('. someClass'); làm việc hoàn toàn tốt
Nishant Baranwal

10

Bạn nên tiêm $ document vào bộ điều khiển của mình và sử dụng nó thay vì đối tượng tài liệu gốc.

var myElement = angular.element($document[0].querySelector('#MyID'))

Nếu bạn không cần gói phần tử kiểu jquery, $ document [0] .querySelector ('# MyID') sẽ cung cấp cho bạn đối tượng DOM.


1
Bạn cũng có thể chỉ tham khảo window.document trực tiếp thay vì sử dụng chi phí dịch vụ tài liệu Angenses $.
MatBee

5
Tất nhiên là bạn có thể nếu bạn không lo lắng về việc chế nhạo tài liệu $ trong lúc không may nhất
Adamy

Tôi không rõ ràng: Tôi nhận được cảnh báo này: Bạn nên sử dụng dịch vụ $ document thay vì đối tượng tài liệu mặc định, nhưng điều đó có nghĩa là gì? Bất kỳ tài liệu về nó? Cảm ơn!
chú thích

@realnot bạn có thể truy cập Đối tượng Tài liệu DOM DOM từ bất kỳ đâu trong javascript của bạn. w3schools.com/jsref/dom_obj_document.asp
Adamy

6

Điều này làm việc cho tôi tốt.

angular.forEach(element.find('div'), function(node)
{
  if(node.id == 'someid'){
    //do something
  }
  if(node.className == 'someclass'){
    //do something
  }
});

3
yếu tố không xác định? angular.element.find không phải là một chức năng để tôi thử bạn mà không có JQuery.
hạ cánh

3
Xin đừng làm điều này. Sử dụng một trong những ví dụ khác. Điều này sử dụng không có tối ưu hóa tra cứu bảng băm ở tất cả.
MatBee

4

Cải thiện câu trả lời của kaiser:

var myEl = $document.find('#some-id');

Đừng quên tiêm $documentvào chỉ thị của bạn


21
Như đã đề cập trong tài liệu góc cho Element.find : find() - Limited to lookups by tag name, nó không hoạt động trên id. Ngoài ra, bạn có một đóng cửa thêm ).
paaat

3

Có lẽ tôi đến quá muộn ở đây nhưng điều này sẽ hoạt động:

var target = angular.element(appBusyIndicator);

Lưu ý, không có appBusyIndicator, nó là giá trị ID đơn giản.

Điều gì đang xảy ra đằng sau hậu trường: (giả sử nó được áp dụng trên div) (được lấy từ dòng angular.js số: 2769 trở đi ...)

/////////////////////////////////////////////
function JQLite(element) {     //element = div#appBusyIndicator
  if (element instanceof JQLite) {
    return element;
  }

  var argIsString;

  if (isString(element)) {
    element = trim(element);
    argIsString = true;
  }
  if (!(this instanceof JQLite)) {
    if (argIsString && element.charAt(0) != '<') {
      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
    }
    return new JQLite(element);
  }

Theo mặc định nếu không có jQuery trên trang, jqLite sẽ được sử dụng. Đối số được hiểu bên trong là id và đối tượng jQuery tương ứng được trả về.


Tôi đã thử điều này ngay bây giờ với Angular 1.5.8. ID đơn giản trả về kết quả trống. angular.element("#myId")hoạt động tốt
Gosha U.

có lẽ bạn có jQuery trên trang của bạn?
Vishal Anand
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.