HTML DOM Collections trong JavaScript
JavaScript HTML DOM | by
Trong JavaScript, khi làm việc với HTML DOM, chúng ta thường cần truy xuất và thao tác với nhiều phần tử trên trang web cùng một lúc. Để làm điều này, HTML DOM Collections cung cấp các danh sách động chứa các phần tử DOM, giúp lập trình viên dễ dàng truy vấn và chỉnh sửa nội dung trang web hiệu quả hơn.
Các HTML DOM Collections phổ biến bao gồm HTMLCollection và NodeList. Chúng giúp lấy danh sách các phần tử dựa trên thẻ HTML, class, ID, hoặc các nhóm phần tử đặc biệt như danh sách hình ảnh, biểu mẫu, liên kết... Tuy nhiên, mỗi loại DOM Collection có đặc điểm và cách sử dụng khác nhau, đòi hỏi chúng ta phải hiểu rõ để áp dụng đúng trong từng tình huống.
Bài viết này sẽ giúp bạn hiểu rõ về HTML DOM Collections, cách thao tác với HTMLCollection và NodeList, sự khác biệt giữa chúng, và ứng dụng thực tế trong lập trình JavaScript.
HTML DOM Collections là gì?
HTML DOM Collections là một đối tượng trong JavaScript, đại diện cho các danh sách phần tử DOM trong một tài liệu HTML. Những Collections này chứa các phần tử (elements) được tìm thấy trong trang web, và chúng cung cấp các phương thức và thuộc tính để truy cập, thao tác và cập nhật các phần tử đó. Những Collections phổ biến nhất là HTMLCollection và NodeList.
-
HTMLCollection: Là một danh sách các phần tử trong tài liệu HTML. Các phần tử này có thể là các thẻ HTML như
<div>
,<p>
,<span>
, và nhiều loại thẻ khác. Một HTMLCollection có thể được truy xuất qua các phương thức nhưgetElementsByTagName()
,getElementsByClassName()
, và các thuộc tính đặc biệt nhưdocument.forms
,document.images
,document.links
. -
NodeList: Là một danh sách các node (nút), không chỉ chứa các phần tử mà còn có thể chứa các node văn bản (Text nodes) và các node khác. Một NodeList có thể được truy xuất qua các phương thức như
querySelectorAll()
. NodeList cũng có thể là động (live) hoặc tĩnh (static) tùy vào cách mà nó được tạo ra.
Sự khác biệt giữa DOM Collections và Array thông thường
Mặc dù cả DOM Collections và Array đều là các danh sách (collections) của các phần tử, nhưng chúng có một số điểm khác biệt quan trọng:
Loại phần tử:
-
DOM Collections (HTMLCollection, NodeList) chứa các DOM nodes, là các phần tử trong cây DOM của tài liệu HTML. Điều này có nghĩa là các phần tử trong Collections không chỉ có thể là các phần tử HTML mà còn có thể là các nodes khác như Text nodes hoặc Comment nodes.
-
Array chứa các phần tử có thể là bất kỳ loại dữ liệu nào (số, chuỗi, đối tượng, v.v.).
Khả năng thay đổi:
-
HTMLCollection và NodeList là các danh sách động (live collections), có nghĩa là chúng tự động cập nhật khi có sự thay đổi trong DOM (như khi một phần tử được thêm vào hoặc xóa đi). Tuy nhiên, NodeList lấy được từ
querySelectorAll()
thường là tĩnh và không cập nhật khi DOM thay đổi. -
Array là tĩnh và không tự động cập nhật. Nếu bạn thay đổi mảng, bạn cần thực hiện thao tác cụ thể để cập nhật giá trị của nó.
Các phương thức:
-
DOM Collections không hỗ trợ nhiều phương thức mạnh mẽ của Array, ví dụ như
map()
,filter()
, hoặcreduce()
. Tuy nhiên, bạn có thể duyệt qua chúng bằng vòng lặpfor
hoặc sử dụng các phương thức tương tự nhưforEach()
(đối với NodeList). -
Array có hỗ trợ đầy đủ các phương thức thao tác mạnh mẽ như
map()
,filter()
,forEach()
,reduce()
, và nhiều phương thức khác.
Chuyển đổi giữa DOM Collections và Array:
-
Bạn có thể dễ dàng chuyển đổi HTMLCollection hoặc NodeList thành Array bằng cách sử dụng
Array.from()
hoặc spread operator (...
). Điều này cho phép bạn tận dụng các phương thức của Array trên các Collection này.
let divs = document.getElementsByTagName("div"); let divArray = Array.from(divs); // Chuyển đổi HTMLCollection thành Array divArray.forEach(div => { console.log(div); });
Tại sao cần sử dụng DOM Collections trong JavaScript?
DOM Collections giúp lập trình viên thao tác với nhóm phần tử DOM mà không cần phải truy xuất từng phần tử một cách riêng biệt. Việc sử dụng DOM Collections mang lại nhiều lợi ích, bao gồm:
-
Tính linh hoạt và hiệu quả: Khi cần truy xuất và thao tác với nhiều phần tử có cùng đặc điểm (như tất cả các thẻ
<p>
, tất cả các phần tử có class "highlight", hoặc tất cả các hình ảnh trên trang), DOM Collections giúp bạn làm điều này dễ dàng mà không phải lặp lại mã nguồn quá nhiều lần. -
Cập nhật động: HTMLCollection là một loại Collection động, nghĩa là khi trang HTML thay đổi (ví dụ như thêm hoặc xóa phần tử), HTMLCollection sẽ tự động cập nhật mà không cần phải gọi lại phương thức để lấy lại danh sách.
-
Tối ưu hóa hiệu suất: Khi làm việc với nhiều phần tử trên trang web, việc sử dụng DOM Collections giúp tiết kiệm thời gian và giảm thiểu sự phức tạp trong việc xử lý từng phần tử. Thao tác với các Collection giúp tránh phải lặp lại mã trong trường hợp cần làm việc với nhiều phần tử cùng loại.
Các loại HTML DOM Collections trong JavaScript
HTMLCollection
HTMLCollection là một đối tượng đại diện cho một tập hợp các phần tử HTML trong tài liệu DOM. Nó là một dạng đặc biệt của DOM Collection mà chỉ chứa Element Nodes. HTMLCollection là danh sách các phần tử được trả về khi bạn truy xuất các phần tử DOM thông qua các phương thức như getElementsByTagName()
, getElementsByClassName()
hoặc các thuộc tính của tài liệu như document.forms
, document.images
, document.links
.
Đặc điểm của HTMLCollection:
-
Dynamic: Là danh sách động, nghĩa là nó sẽ tự động cập nhật khi có thay đổi trong DOM (ví dụ: khi một phần tử bị thêm vào hoặc xóa đi).
-
Không hỗ trợ phương thức forEach: Mặc dù HTMLCollection có thể được duyệt qua bằng vòng lặp
for
, nhưng không hỗ trợ phương thứcforEach()
như NodeList.
Cách truy xuất phần tử từ HTMLCollection
Bạn có thể truy xuất phần tử từ HTMLCollection bằng cách sử dụng chỉ mục (index) giống như một mảng (array) hoặc qua các phương thức cụ thể của DOM. Dưới đây là các cách phổ biến để truy xuất HTMLCollection:
getElementsByTagName(tagName): Trả về một HTMLCollection chứa tất cả các phần tử có tên thẻ cụ thể.
let divs = document.getElementsByTagName("div");
getElementsByClassName(className): Trả về một HTMLCollection chứa tất cả các phần tử có class name cụ thể.
let elements = document.getElementsByClassName("highlight");
document.forms: Trả về một HTMLCollection chứa tất cả các form trong trang web.
let forms = document.forms;
document.images: Trả về một HTMLCollection chứa tất cả các hình ảnh trong trang web.
let images = document.images;
Các phương thức làm việc với HTMLCollection
Các phương thức cơ bản để làm việc với HTMLCollection bao gồm:
-
item(index): Trả về phần tử tại chỉ mục cụ thể trong HTMLCollection. (Tương tự như sử dụng chỉ mục của mảng).
let firstDiv = divs.item(0); // Trả về phần tử div đầu tiên trong HTMLCollection
let firstDiv = divs.item(0); // Trả về phần tử div đầu tiên trong HTMLCollection
console.log(divs.length); // In ra số lượng phần tử div trong HTMLCollection
for loop: Vì HTMLCollection là một đối tượng có thể duyệt qua bằng chỉ mục, bạn có thể dùng vòng lặp for
để duyệt qua các phần tử.
for (let i = 0; i < divs.length; i++) { console.log(divs[i]); }
Sự khác biệt giữa HTMLCollection và NodeList
NodeList có thể chứa bất kỳ loại node nào (bao gồm các Text Nodes, Comment Nodes, Element Nodes), trong khi HTMLCollection chỉ chứa Element Nodes.
HTMLCollection là danh sách động và tự động cập nhật khi có thay đổi trong DOM (thêm, xóa phần tử). Tuy nhiên, NodeList có thể là tĩnh hoặc động:
-
Tĩnh: Được trả về khi sử dụng
querySelectorAll()
. -
Động: Được trả về khi sử dụng các phương thức như
getElementsByTagName()
.
HTMLCollection không hỗ trợ forEach(), trong khi NodeList (như được trả về từ querySelectorAll()
) hỗ trợ phương thức này.
NodeList
NodeList là một đối tượng tương tự như HTMLCollection, nhưng nó có thể chứa tất cả các types of nodes (không chỉ Element Nodes mà còn Text Nodes và Comment Nodes). NodeList được trả về khi sử dụng các phương thức như querySelectorAll()
, childNodes
và một số phương thức khác.
Một điểm đặc biệt của NodeList là nó có thể là tĩnh (static) hoặc động (live), tùy thuộc vào cách bạn lấy NodeList:
-
Động: Các NodeList trả về từ các phương thức như
getElementsByTagName()
hoặcgetElementsByClassName()
sẽ tự động cập nhật khi có sự thay đổi trong DOM. -
Tĩnh: Các NodeList trả về từ
querySelectorAll()
sẽ không thay đổi nếu DOM thay đổi.
Cách lấy danh sách phần tử trong NodeList
Các phương thức chính để lấy NodeList bao gồm:
querySelectorAll(selector): Trả về một NodeList chứa tất cả các phần tử khớp với selector CSS.
let divs = document.querySelectorAll("div");
childNodes: Trả về một NodeList chứa tất cả các con của một phần tử, bao gồm cả các Text Nodes và Comment Nodes.
let children = document.getElementById("parent").childNodes;
Duyệt qua NodeList bằng forEach và for loop
-
forEach: NodeList (từ
querySelectorAll()
) hỗ trợ phương thứcforEach()
để duyệt qua các phần tử, giúp dễ dàng thao tác với từng phần tử mà không cần sử dụng chỉ mục.
let divs = document.querySelectorAll("div"); divs.forEach((div) => { console.log(div); });
for loop: Bạn cũng có thể duyệt qua NodeList bằng vòng lặp for
nếu cần hỗ trợ các phiên bản trình duyệt cũ hơn không hỗ trợ forEach()
.
let divs = document.querySelectorAll("div"); for (let i = 0; i < divs.length; i++) { console.log(divs[i]); }
Cách làm việc với HTML DOM Collections trong JavaScript
Truy xuất các phần tử từ DOM Collections
getElementsByTagName()
Phương thức getElementsByTagName()
trả về một HTMLCollection chứa tất cả các phần tử có tên thẻ cụ thể trong tài liệu HTML. Phương thức này có thể được sử dụng để tìm tất cả các phần tử của một loại thẻ nhất định.
Ví dụ: Truy xuất tất cả các phần tử <div>
trong tài liệu HTML:
let divs = document.getElementsByTagName("div"); console.log(divs); // HTMLCollection chứa tất cả các phần tử <div>
-
Trả về: HTMLCollection chứa các phần tử có tên thẻ tương ứng.
-
Cách sử dụng: Để lấy từng phần tử, bạn có thể sử dụng chỉ mục như trong mảng.
let firstDiv = divs[0]; // Truy xuất phần tử div đầu tiên trong HTMLCollection
getElementsByClassName()
Phương thức getElementsByClassName()
trả về một HTMLCollection chứa tất cả các phần tử có class name cụ thể trong tài liệu HTML.
Ví dụ: Truy xuất tất cả các phần tử có class "highlight"
:
let elements = document.getElementsByClassName("highlight"); console.log(elements); // HTMLCollection chứa các phần tử có class "highlight"
-
Trả về: HTMLCollection chứa các phần tử có class name tương ứng.
-
Cách sử dụng: Các phần tử trong HTMLCollection có thể được truy xuất bằng chỉ mục hoặc vòng lặp.
document.forms, document.images, document.links
-
document.forms: Trả về một HTMLCollection chứa tất cả các form trong tài liệu HTML.
-
document.images: Trả về một HTMLCollection chứa tất cả các hình ảnh (
<img>
) trong tài liệu. -
document.links: Trả về một HTMLCollection chứa tất cả các liên kết (
<a>
) trong tài liệu.
Ví dụ:
let forms = document.forms; // HTMLCollection chứa tất cả các form let images = document.images; // HTMLCollection chứa tất cả các hình ảnh let links = document.links; // HTMLCollection chứa tất cả các liên kết
Duyệt qua HTML DOM Collections
Dùng vòng lặp for
Vì HTMLCollection giống mảng (array) nhưng không hoàn toàn là một mảng thực thụ, bạn có thể duyệt qua nó bằng vòng lặp for
để thao tác với các phần tử.
Ví dụ: Duyệt qua HTMLCollection chứa các phần tử <div>
:
let divs = document.getElementsByTagName("div"); for (let i = 0; i < divs.length; i++) { console.log(divs[i]); // In ra từng phần tử div trong HTMLCollection }
Dùng forEach (NodeList)
NodeList (như được trả về từ querySelectorAll()
) hỗ trợ phương thức forEach()
, giúp bạn dễ dàng duyệt qua các phần tử mà không cần sử dụng vòng lặp for
.
Ví dụ:
let divs = document.querySelectorAll("div"); divs.forEach((div) => { console.log(div); // In ra từng phần tử div trong NodeList });
Lưu ý: HTMLCollection không hỗ trợ trực tiếp phương thức forEach()
, nên nếu bạn muốn sử dụng forEach()
với HTMLCollection, bạn cần phải chuyển nó thành Array trước.
Chuyển đổi HTMLCollection thành Array để dễ thao tác
Vì HTMLCollection không hỗ trợ một số phương thức như forEach()
, bạn có thể chuyển đổi nó thành một Array để tận dụng các phương thức mạnh mẽ của mảng như map()
, forEach()
, filter()
, v.v.
Cách chuyển đổi:
let divs = document.getElementsByTagName("div"); let divArray = Array.from(divs); // Chuyển HTMLCollection thành Array divArray.forEach((div) => { console.log(div); // Duyệt qua Array sử dụng forEach });
Hoặc bạn có thể sử dụng spread operator:
let divArray = [...divs]; // Chuyển HTMLCollection thành Array
Thay đổi nội dung và thuộc tính của các phần tử trong DOM Collections
Cập nhật nội dung của các phần tử trong danh sách
Để thay đổi nội dung của các phần tử trong HTMLCollection hoặc NodeList, bạn có thể sử dụng các thuộc tính như innerHTML
, textContent
, hoặc nodeValue
(với các Text Node). Sau đây là cách cập nhật nội dung:
Ví dụ: Thay đổi nội dung của tất cả các phần tử <p>
trong danh sách:
let paragraphs = document.getElementsByTagName("p"); for (let i = 0; i < paragraphs.length; i++) { paragraphs[i].textContent = "Nội dung mới"; // Cập nhật nội dung văn bản }
Hoặc nếu bạn muốn thay đổi nội dung HTML bên trong phần tử, bạn có thể sử dụng innerHTML
:
let divs = document.getElementsByTagName("div"); for (let i = 0; i < divs.length; i++) { divs[i].innerHTML = "<strong>Nội dung mới</strong>"; // Cập nhật HTML bên trong }
Thêm/xóa class cho các phần tử
Để thay đổi lớp CSS (class) của các phần tử trong HTMLCollection, bạn có thể sử dụng các phương thức classList
như add()
, remove()
, toggle()
.
Ví dụ: Thêm và xóa class cho tất cả các phần tử có class "highlight"
:
let elements = document.getElementsByClassName("highlight"); for (let i = 0; i < elements.length; i++) { elements[i].classList.add("active"); // Thêm class "active" elements[i].classList.remove("highlight"); // Xóa class "highlight" }
Hoặc để thay đổi class bằng cách sử dụng toggle()
:
let divs = document.querySelectorAll("div"); divs.forEach((div) => { div.classList.toggle("highlight"); // Thêm hoặc xóa class "highlight" });
Cập nhật thuộc tính như src, href, value
Bạn có thể thay đổi các thuộc tính như src
(với hình ảnh), href
(với liên kết), và value
(với các trường nhập liệu) của các phần tử trong DOM Collections.
Ví dụ: Cập nhật thuộc tính src
của tất cả các thẻ <img>
:
let images = document.getElementsByTagName("img"); for (let i = 0; i < images.length; i++) { images[i].src = "new_image.jpg"; // Thay đổi thuộc tính src của hình ảnh }