Phương thức querySelectorAll và getElementsBy * trả về gì?
Đỗ getElementsByClassName
(và chức năng tương tự như getElementsByTagName
và querySelectorAll
) làm việc giống như getElementById
hay họ trả về một mảng của các nguyên tố?
Lý do tôi hỏi là vì tôi đang cố gắng thay đổi kiểu của tất cả các phần tử đang 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';
Trả lời
getElementById()
Mã của bạn hoạt động vì 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 null
nếu không tìm thấy phần tử nào).
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:
var elems = document.getElementsByClassName('myElement');
for(var i = 0; i < elems.length; i++) {
elems[i].style.size = '100px';
}
Nếu bạn thích thứ gì đó ngắn hơn, hãy cân nhắc sử dụng jQuery :
$('.myElement').css('size', '100px');
Bạn đang sử dụng một mảng làm đối tượng, sự khác biệt giữa getElementbyId
và
getElementsByClassName
là:
getElementbyId
sẽ trả về một đối tượng Phần tử hoặc null nếu không tìm thấy phần tử nào có IDgetElementsByClassName
sẽ trả về bộ sưu tập HTMLC trực tiếp , có thể có độ dài bằng 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ộtNodeList
đối tượng trực tiếp 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ố đó, lấy đượ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 nà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
getElementById
Phương thức getElementById () truy cập phần tử đầu tiên với id đã chỉ định.
https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById
trong mã của bạn các dòng:
1- document.getElementsByClassName ('myElement'). Style.size = '100px';
sẽ KHÔNG hoạt động như mong đợi, vì getElementByClassName
sẽ trả về một mảng và mảng sẽ KHÔNG có thuộc style
tính, bạn có thể truy cập từng thuộc tính element
bằng cách lặp qua chúng.
Đó là lý do tại sao hàm getElementById
là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 style
tài sản.
Mô tả sau đượ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 một đố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ử có 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ố getElementsByClassName
sẽ chấp nhận một tên lớp.
Nếu đây là nội dung 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 mảng) gồm 3 chữ cái trên <div>
, vì chúng khớp với tên lớp đã cho.
Sau đó, bạn có thể lặp lại tập hợp các nút này ( <div>
trong trường hợp 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 đăng này để biết thêm về sự khác biệt giữa các phần tử và các nút.
ES6 cung cấp Array.from()
phương thức, phương thức này tạo ra một thể hiện Mảng mới từ một đối tượng giống mảng hoặc có thể 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ùng một giải pháp 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>
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 tạo ra một mảng, nó là một giá trị duy nhất. Tương tự nhưdocument.getElementById()
chỉ tìm nạp 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 được chỉ định và trả về chúng trong một mảng. Tương tự như chỉdocument.getElementsByClassName()
dành cho các lớp vàdocument.getElementsByTagName()
thẻ.
Tại sao sử dụng querySelector?
Nó chỉ được sử dụng với mục đích duy nhất là dễ dàng và ngắn gọn.
Tại sao sử dụng getElement / sBy? *
Hiệu suất nhanh hơn.
Tại sao sự khác biệt về hiệu suất này?
Cả hai cách lựa chọn đều có mục đích tạo NodeList để sử dụng thêm.
querySelectors tạo ra một NodeList tĩnh với các bộ chọn do đó nó phải được tạo từ đầu.
getElement / sBy * ngay lập tức điều chỉnh NodeList hiện có của DOM hiện tại.
Vì vậy, khi nào sử dụng phương pháp nào là tùy thuộc vào bạn / dự án của bạn / thiết bị của bạn.
Infos
Demo tất cả các phương pháp Kiểm tra hiệu suất
tài liệu NodeList
Nó trả về danh sách giống như mảng.
Bạn làm cho nó một Mảng làm ví dụ
var el = getElementsByClassName("elem");
el = Array.prototype.slice.call(el); //this line
el[0].appendChild(otherElem);
Bạn có thể nhận được một phần 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 .myElement.
Nếu bạn muốn áp dụng điều này cho tất cả các phần 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';
});
/*
* 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
Với ES5 + (bất kỳ được duyệt hiện nay - 2017), bạn sẽ có thể làm
[].forEach.call(document.getElementsByClassName('answer'), function(el) {
el.style.color= 'red';
});
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 hoạt động cho bất kỳ word
phần tử nào và chuyển vào số 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>