Các phương thức querySelectorAll và getElementsBy * trả về cái gì?


151

Do getElementsByClassName(và các chức năng tương tự như getElementsByTagNamequerySelectorAll) hoạt động giống như getElementByIdhoặc chúng trả về một mảng các phần tử?

Lý do tôi hỏi là vì tôi đang cố gắng thay đổi phong cách của tất cả các yếu tố sử dụng getElementsByClassName. Xem bên dưới.

//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';

//works
document.getElementById('myIdElement').style.size = '100px';

37
Manh mối là, rất nhiều, trong tên: getElementsByClassName()ngụ ý số nhiều, trong khi getElementById()ngụ ý một mục yếu tố số ít.
David nói phục hồi Monica

1
Tôi hiểu điều đó, điều đó không có nghĩa với tôi rằng bạn không thể thay đổi tất cả các yếu tố với tên lớp đó bằng cách sử dụng mã ở trên thay vì phải lặp qua một mảng. cách jquery tốt hơn nhiều, tôi chỉ tò mò về cách js
dmo

1
Cũng có thể hữu ích: stackoverflow.com/questions/3871547/ từ
kapa

Câu trả lời:


152

getElementById()Mã của bạn hoạt động do ID phải là duy nhất và do đó hàm luôn trả về chính xác một phần tử (hoặc nullnếu không tìm thấy).

Tuy nhiên, getElementsByClassName(), querySelectorAll(), và các getElementsBy*phương pháp trả về một bộ sưu tập mảng giống như các yếu tố. Lặp lại nó giống như bạn làm với một mảng thực sự:

var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
    elems[i].style.size = '100px';
}

Nếu bạn thích một cái gì đó ngắn hơn, hãy xem xét sử dụng jQuery :

$('.myElement').css('size', '100px');

1
Điều đó cũng áp dụng cho <iframe>cũng là một phần của miền của bạn
JMASTER B

3
Đó là năm 2018 ... Chỉ cần tạo một hàm bao bọc cho querySelectorAll()và bạn có thể có mã ngắn đẹp mà không cần phụ thuộc vào trường học lớn. qSA(".myElement").forEach(el => el.style.size = "100px")Có thể có trình bao bọc nhận được một cuộc gọi lại. qSA(".myElement", el => el.style.size = "100px")

2
"Nếu bạn thích một cái gì đó ngắn hơn, hãy xem xét thêm một thư viện khổng lồ vào dự án của bạn" Tôi biết năm 2012 là một thời điểm khác, nhưng ngay cả khi đó tôi sẽ thấy rằng bit đó là lố bịch.
CoryCoolguy

1
" Lặp đi lặp lại giống như bạn thực hiện với một mảng thực sự , Care Care , getElementsByClassName trả về một NodeList trực tiếp có thể bị sửa đổi bất ngờ trong vòng lặp, ví dụ: nếu tên lớp mà chúng được chọn bị xóa .;-)
RobG

20

Bạn đang sử dụng một mảng làm đối tượng, sự khác biệt giữa getElementbyIdgetElementsByClassNamelà:

  • getElementbyIdsẽ trả về một đối tượng Element hoặc null nếu không tìm thấy phần tử nào có ID
  • getElementsByClassNamesẽ trả về HTMLCollection trực tiếp , có thể có độ dài 0 nếu không tìm thấy phần tử phù hợp

getElementsByClassName

Các getElementsByClassName(classNames)phương pháp có một chuỗi chứa hổn độn của các thẻ không gian tách biệt độc đáo đại diện cho các lớp học. Khi được gọi, phương thức phải trả về một NodeListđối tượng sống chứa tất cả các phần tử trong tài liệu có tất cả các lớp được chỉ định trong đối số đó, có được các lớp bằng cách tách một chuỗi trên khoảng trắng. Nếu không có mã thông báo được chỉ định trong đối số, thì phương thức phải trả về một NodeList trống.

https://www.w3.org/TR/2008/WD-html5-20080610/dom.html#getelementsbyclassname

getEuityById

Phương thức getEuityById () truy cập phần tử đầu tiên với id được chỉ định.

https://developer.mozilla.org/en-US/docs/Web/API/Document/getEuityById

trong mã của bạn các dòng:

1- document.getElementsByClassName ('myEuity'). Style.size = '100px';

sẽ KHÔNG hoạt động như mong đợi, vì getElementByClassNamesẽ trả về một mảng và mảng sẽ KHÔNG có thuộc styletính, bạn có thể truy cập từng mảng elementbằng cách lặp qua chúng.

Đó là lý do tại sao hàm getElementByIdlàm việc cho bạn, hàm này sẽ trả về đối tượng trực tiếp. Do đó, bạn sẽ có thể truy cập vào styletài sản.


Lưu ý rằng các thông số kỹ thuật whatwg đang được trình duyệt triển khai thực hiện khác với các thông số w3c ở đây, các trình duyệt trước đây (và do đó là các trình duyệt hiện tại) trả về HTMLCollection cho getElementsByClassName, không phải là NodeList. Nhỏ, nhưng có thể nhầm lẫn một số.
Kaiido

@ Kaiido, sự khác biệt thực tế là được? Theo hiểu biết của tôi, NodeList là một tập hợp các phần tử DOM chung và có sẵn trong bất kỳ DOM nào, không chỉ là DOM DOM (ví dụ: DOM DOM), trong khi HTMLCollection dành cho DOM DOM (rõ ràng). Sự khác biệt duy nhất tôi có thể thấy là phương thức nameItem của HTMLCollection .
RobG

PS Nit pick: liên kết cho Tiêu chuẩn sống WHATWG HTMLtiêu chuẩn W3C HTML 5.2 . Được chiều chuộng bởi sự lựa chọn. ;-) Làm cho không có sự khác biệt với điểm bạn nêu ra mặc dù.
RobG

@RobG NodeList có nhiều phương thức không thể truy cập trên HTMLCollection.
Kaiido

@ Kaiido-chắc chắn, nhưng foreach không được xác định như là một phần của giao diện cho một trong hai bộ sưu tập hoặc NodeList bởi W3C hay WHATWG, nó quy định riêng, ví dụ như một thuộc tính của bộ sưu tập chung trong Web IDL đặc điểm kỹ thuật như vậy nên áp dụng cho cả các bộ sưu tập và NodeLists (mặc dù tôi chấp nhận quan điểm của bạn rằng bộ sưu tập được trả về bởi getElementsByClassName không có phương thức forEach ). Tôi đoán điểm mấu chốt là có đủ câu chuyện cho một câu trả lời hay để kể nó. :-)
RobG

11

Mô tả sau đây được lấy từ trang này :

Phương thức getElementsByClassName () trả về một tập hợp tất cả các phần tử trong tài liệu với tên lớp được chỉ định, dưới dạng đối tượng NodeList.

Đối tượng NodeList đại diện cho một tập hợp các nút. Các nút có thể được truy cập bằng số chỉ mục. Chỉ số bắt đầu từ 0.

Mẹo: Bạn có thể sử dụng thuộc tính độ dài của đối tượng NodeList để xác định số lượng phần tử với tên lớp được chỉ định, sau đó bạn có thể lặp qua tất cả các phần tử và trích xuất thông tin bạn muốn.

Vì vậy, như một tham số getElementsByClassNamesẽ chấp nhận một tên lớp.

Nếu đây là phần thân HTML của bạn:

<div id="first" class="menuItem"></div>
<div id="second" class="menuItem"></div>
<div id="third" class="menuItem"></div>
<div id="footer"></div>

sau đó var menuItems = document.getElementsByClassName('menuItem')sẽ trả về một tập hợp (không phải là một mảng) của 3 chữ trên <div>, vì chúng khớp với tên lớp đã cho.

Sau đó, bạn có thể lặp lại <div>bộ sưu tập ( các trường hợp này) trong các nút này với:

for (var menuItemIndex = 0 ; menuItems.length ; menuItemIndex ++) {
   var currentMenuItem = menuItems[menuItemIndex];
   // do stuff with currentMenuItem as a node.
}

Vui lòng tham khảo bài viết này để biết thêm về sự khác biệt giữa các yếu tố và các nút.


11

ES6 cung cấp Array.from()phương thức, tạo ra một cá thể Array mới từ một đối tượng giống như mảng hoặc lặp lại.

let boxes = document.getElementsByClassName('box');

Array.from(boxes).forEach(v => v.style.background = 'green');
console.log(Array.from(boxes));
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>

Như bạn có thể thấy bên trong đoạn mã, sau khi sử dụng Array.from()hàm, bạn có thể thao tác trên từng phần tử.


Các giải pháp tương tự sử dụng jQuery.

$('.box').css({'background':'green'});
.box {
  width: 50px;
  height: 50px;
  margin: 5px;
  background: blue;
  display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>


7

Nói cách khác

  • document.querySelector()chỉ chọn một phần tử đầu tiên của bộ chọn được chỉ định. Vì vậy, nó không phun ra một mảng, đó là một giá trị duy nhất. Tương tự như document.getElementById()chỉ tìm nạp các phần tử ID, vì ID phải là duy nhất.

  • document.querySelectorAll()chọn tất cả các phần tử với bộ chọn đã chỉ định và trả về chúng trong một mảng. Tương tự như chỉ document.getElementsByClassName()cho các lớp và document.getElementsByTagName()thẻ.


Tại sao nên sử dụng querySelector?

Nó chỉ được sử dụng cho mục đích duy nhất là dễ dàng và ngắn gọn.


Tại sao nên sử dụng getEuity / sBy? *

Hiệu suất nhanh hơn.


Tại sao hiệu suất này khác nhau?

Cả hai cách lựa chọn đều có mục đích tạo NodeList để sử dụng tiếp. querySelector tạo ra một NodeList tĩnh với các bộ chọn do đó nó phải được tạo trước tiên từ đầu.
getEuity / sBy * ngay lập tức điều chỉnh NodeList trực tiếp hiện có của DOM hiện tại.

Vì vậy, khi nào nên sử dụng phương pháp nào tùy thuộc vào bạn / dự án / thiết bị của bạn.


Thông tin

Bản demo của tất cả các phương pháp Kiểm tra hiệu năng
tài liệu NodeList


4

Nó trả về danh sách giống như Array.

Bạn làm cho một mảng làm ví dụ

var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);  

4

Bạn có thể có được một yếu tố duy nhất bằng cách chạy

document.querySelector('.myElement').style.size = '100px';

nhưng nó sẽ hoạt động cho phần tử đầu tiên với lớp .myEuity.

Nếu bạn muốn áp dụng điều này cho tất cả các yếu tố với lớp tôi khuyên bạn nên sử dụng

document.querySelectorAll('.myElement').forEach(function(element) {
    element.style.size = '100px';
});

4
/*
 * To hide all elements with the same class, 
 * use looping to reach each element with that class. 
 * In this case, looping is done recursively
 */

const hideAll = (className, i=0) => {
if(!document.getElementsByClassName(className)[i]){ //exits the loop when element of that id does not exist
  return; 
}

document.getElementsByClassName(className)[i].style.visibility = 'hidden'; //hide element
return hideAll(className, i+1) //loop for the next element
}

hideAll('appBanner') //the function call requires the class name

0

Với ES5 + (bất kỳ ngày nay đã được duyệt - 2017), bạn sẽ có thể làm

[].forEach.call(document.getElementsByClassName('answer'), function(el) {
    el.style.color= 'red';
});


0

Một câu trả lời cho trường hợp cụ thể của Drenzii ...

Bạn có thể tạo một hàm sẽ hoạt động cho bất kỳ wordphần tử nào và chuyển số lượng của phần tử bạn muốn chuyển đổi, như:

// Binds `wordButtons` to an (array-like) HTMLCollection of buttons
const wordButtons = document.getElementsByClassName("word");

// Applies the `slantWord` function to the first word button
slantWord(1);

// Defines the `slantWord` function
function slantWord(wordNumber) {
  const index = wordNumber - 1; // Collection index is zero-based
  wordButtons[index].style.transform = "rotate(7deg)"; // Transforms the specified button
}
<div class="wordGameContainer">
  <button class="word word1">WORD 1</button>
  <button class="word word2">WORD 2</button>
  <button class="word word3">WORD 3</button>
  <button class="word word4">WORD 4</button>
</div>

<div>
  <button onclick="moveWord()" class="playButton">PLAY</button>
</div>

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.