DOM Navigation với HTML DOM trong JavaScript
JavaScript HTML DOM | by
Trong lập trình web, Document Object Model (DOM) đóng vai trò như một cầu nối giữa JavaScript và nội dung của trang web. DOM cho phép lập trình viên truy cập, thao tác và thay đổi các phần tử HTML một cách linh hoạt. Để làm được điều này, DOM Navigation (Điều hướng DOM) cung cấp các phương pháp giúp di chuyển giữa các phần tử trong cây DOM, từ phần tử cha, phần tử con đến các phần tử anh chị em. Việc nắm vững DOM Navigation không chỉ giúp cải thiện hiệu suất thao tác với trang web mà còn là nền tảng quan trọng để xây dựng các ứng dụng web tương tác. Trong bài viết này, mình sẽ cùng tìm hiểu về các phương pháp điều hướng trong DOM và cách ứng dụng chúng trong thực tế.
Giới thiệu về DOM và DOM Navigation trong JavaScript
DOM (Document Object Model) là gì?
DOM (Document Object Model) là một mô hình lập trình đại diện cho cấu trúc của một tài liệu HTML hoặc XML dưới dạng một cây phân cấp. Khi trình duyệt tải một trang web, nó sẽ tạo ra một phiên bản DOM của trang, trong đó mỗi phần tử HTML được coi là một "node" (nút) trong cây DOM.
DOM cho phép JavaScript truy cập và thao tác các phần tử HTML bằng cách thay đổi nội dung, thuộc tính hoặc kiểu dáng của chúng. Mỗi phần tử trong trang web như <div>
, <p>
, <h1>
, <a>
đều là một node trong DOM và có thể được truy xuất hoặc chỉnh sửa bằng JavaScript.
Ví dụ về một cây DOM đơn giản của một trang HTML:
<!DOCTYPE html> <html> <head> <title>Trang web của tôi</title> </head> <body> <h1>Chào mừng đến với trang web!</h1> <p>Đây là một đoạn văn.</p> </body> </html>
Cấu trúc cây DOM tương ứng với trang HTML trên:
Document │ ├── html │ ├── head │ │ └── title (Trang web của tôi) │ ├── body │ ├── h1 (Chào mừng đến với trang web!) │ ├── p (Đây là một đoạn văn.)
Như vậy, mỗi phần tử HTML là một node trong cây DOM và có thể được JavaScript truy cập và thao tác thông qua DOM API.
DOM Navigation là gì?
DOM Navigation (Điều hướng DOM) là quá trình di chuyển giữa các phần tử trong cây DOM bằng cách sử dụng các thuộc tính JavaScript để truy xuất phần tử cha (parentNode
), phần tử con (childNodes
, children
), hoặc các phần tử anh chị em (previousSibling
, nextSibling
).
DOM Navigation cho phép lập trình viên dễ dàng truy cập vào bất kỳ phần tử nào trong cây DOM và thực hiện các thay đổi động trên trang web mà không cần phải viết lại toàn bộ HTML.
Ví dụ: Nếu chúng ta có đoạn HTML sau:
<ul id="menu"> <li>Trang chủ</li> <li>Dịch vụ</li> <li>Liên hệ</li> </ul>
Ta có thể sử dụng JavaScript để điều hướng giữa các phần tử:
let menu = document.getElementById("menu"); // Lấy phần tử <ul> console.log(menu.children); // Lấy danh sách các phần tử <li> console.log(menu.firstElementChild.textContent); // Lấy nội dung của phần tử đầu tiên ("Trang chủ") console.log(menu.lastElementChild.textContent); // Lấy nội dung của phần tử cuối cùng ("Liên hệ")
Tầm quan trọng của DOM Navigation trong JavaScript
DOM Navigation đóng vai trò quan trọng trong việc phát triển các ứng dụng web động vì nó giúp:
Tương tác với các phần tử HTML một cách linh hoạt
-
Thay đổi nội dung trang web mà không cần tải lại.
-
Dễ dàng thêm, xóa hoặc chỉnh sửa các phần tử HTML.
Cải thiện trải nghiệm người dùng (UX/UI)
-
Hiển thị/ẩn nội dung dựa trên hành động của người dùng.
-
Cập nhật dữ liệu theo thời gian thực mà không cần làm mới trang.
Hỗ trợ xử lý sự kiện hiệu quả hơn
-
Truy cập và gán sự kiện cho các phần tử một cách có tổ chức.
-
Điều hướng giữa các phần tử liên quan trong cùng một nhóm (ví dụ: di chuyển giữa các mục trong danh sách).
Tối ưu hiệu suất của ứng dụng web
-
Giảm số lần truy vấn trực tiếp vào DOM giúp tăng tốc độ xử lý.
-
Giảm việc thao tác không cần thiết trên DOM để tránh ảnh hưởng đến hiệu suất trình duyệt.
Ví dụ về việc thay đổi nội dung động bằng DOM Navigation:
<button id="changeText">Bấm để thay đổi</button> <p id="message">Chào bạn!</p> <script> document.getElementById("changeText").addEventListener("click", function() { let message = document.getElementById("message"); message.textContent = "Nội dung đã được thay đổi!"; }); </script>
Trong ví dụ trên, DOM Navigation giúp chúng ta tìm đến phần tử <p>
và thay đổi nội dung của nó khi người dùng bấm vào nút.
Các phương pháp điều hướng trong DOM trong JavaScript
Điều hướng theo quan hệ cha - con
Cây DOM có cấu trúc phân cấp, trong đó các phần tử có mối quan hệ cha - con. Dưới đây là các phương pháp giúp truy xuất phần tử cha và con trong DOM.
parentNode
– Lấy phần tử cha
-
Thuộc tính
parentNode
dùng để truy xuất phần tử cha (parent) của một phần tử con trong DOM. -
Nếu phần tử không có cha (ví dụ:
document
),parentNode
sẽ trả vềnull
.
Ví dụ:
<div id="parent"> <p id="child">Nội dung đoạn văn</p> </div> <script> let child = document.getElementById("child"); console.log(child.parentNode); // Trả về <div id="parent"> </script>
childNodes
– Lấy tất cả các node con (bao gồm cả text nodes)
-
Thuộc tính
childNodes
trả về danh sách tất cả các node con của phần tử, bao gồm cả text nodes (các khoảng trắng, xuống dòng). -
Đối tượng trả về là một NodeList (giống mảng nhưng không phải mảng thật sự).
Ví dụ:
<ul id="menu"> <li>Trang chủ</li> <li>Dịch vụ</li> </ul> <script> let menu = document.getElementById("menu"); console.log(menu.childNodes); // NodeList chứa cả các khoảng trắng và các <li> </script>
children
– Lấy tất cả các phần tử con (loại bỏ text nodes)
-
children
chỉ trả về các phần tử con mà không bao gồm text nodes. -
Đối tượng trả về là một HTMLCollection (giống mảng nhưng không phải mảng thật sự).
Ví dụ:
<ul id="menu"> <li>Trang chủ</li> <li>Dịch vụ</li> </ul> <script> let menu = document.getElementById("menu"); console.log(menu.children); // HTMLCollection chỉ chứa <li> </script>
firstChild
/ firstElementChild
– Lấy phần tử con đầu tiên
-
firstChild
: Trả về node đầu tiên (có thể là text node). -
firstElementChild
: Trả về phần tử con đầu tiên, bỏ qua text nodes.
Ví dụ:
<div id="container"> <p>Đây là đoạn văn.</p> </div> <script> let container = document.getElementById("container"); console.log(container.firstChild); // Có thể là text node nếu có khoảng trắng console.log(container.firstElementChild); // Trả về <p> </script>
lastChild
/ lastElementChild
– Lấy phần tử con cuối cùng
-
lastChild
: Trả về node cuối cùng (có thể là text node). -
lastElementChild
: Trả về phần tử con cuối cùng, bỏ qua text nodes.
Ví dụ:
<div id="container"> <p>Đây là đoạn văn.</p> </div> <script> let container = document.getElementById("container"); console.log(container.lastChild); // Có thể là text node nếu có khoảng trắng console.log(container.lastElementChild); // Trả về <p> </script>
Điều hướng theo quan hệ anh chị em (siblings)
Các phần tử trên cùng một cấp (cùng có chung một phần tử cha) được gọi là anh chị em (siblings).
previousSibling
/ previousElementSibling
– Lấy phần tử anh/chị phía trước
-
previousSibling
: Lấy node trước phần tử hiện tại (có thể là text node). -
previousElementSibling
: Lấy phần tử trước phần tử hiện tại, bỏ qua text nodes.
Ví dụ:
<ul> <li>Trang chủ</li> <li id="current">Dịch vụ</li> <li>Liên hệ</li> </ul> <script> let current = document.getElementById("current"); console.log(current.previousSibling); // Có thể là text node console.log(current.previousElementSibling); // Trả về <li>Trang chủ</li> </script>
nextSibling
/ nextElementSibling
– Lấy phần tử em phía sau
-
nextSibling
: Lấy node sau phần tử hiện tại (có thể là text node). -
nextElementSibling
: Lấy phần tử sau phần tử hiện tại, bỏ qua text nodes.
Ví dụ:
<ul> <li>Trang chủ</li> <li id="current">Dịch vụ</li> <li>Liên hệ</li> </ul> <script> let current = document.getElementById("current"); console.log(current.nextSibling); // Có thể là text node console.log(current.nextElementSibling); // Trả về <li>Liên hệ</li> </script>
Điều hướng đến phần tử cụ thể
Bên cạnh việc điều hướng theo quan hệ cha - con - anh chị em, ta có thể truy xuất trực tiếp đến phần tử mong muốn bằng các phương thức sau:
getElementById(id)
– Lấy phần tử theo ID
-
Tìm kiếm phần tử HTML dựa trên thuộc tính
id
. -
Trả về phần tử đầu tiên khớp với
id
, nếu không tìm thấy sẽ trả vềnull
.
Ví dụ:
<p id="message">Hello World</p> <script> let message = document.getElementById("message"); console.log(message.textContent); // "Hello World" </script>
getElementsByClassName(className)
– Lấy danh sách phần tử theo class
-
Trả về danh sách tất cả các phần tử có class cụ thể.
-
Kết quả trả về là một
HTMLCollection
.
Ví dụ:
<p class="text">Đoạn 1</p> <p class="text">Đoạn 2</p> <script> let texts = document.getElementsByClassName("text"); console.log(texts[0].textContent); // "Đoạn 1" </script>
getElementsByTagName(tagName)
– Lấy danh sách phần tử theo thẻ
-
Tìm tất cả các phần tử dựa trên tên thẻ (ví dụ:
div
,p
,a
). -
Trả về một
HTMLCollection
.
Ví dụ:
<p>Đoạn 1</p> <p>Đoạn 2</p> <script> let paragraphs = document.getElementsByTagName("p"); console.log(paragraphs.length); // 2 </script>
querySelector(selector)
– Lấy phần tử đầu tiên khớp với selector
-
Tìm phần tử theo cú pháp CSS selector (
#id
,.class
,tag
). -
Trả về phần tử đầu tiên tìm thấy.
Ví dụ:
<p class="text">Đoạn 1</p> <p class="text">Đoạn 2</p> <script> let paragraph = document.querySelector(".text"); console.log(paragraph.textContent); // "Đoạn 1" </script>
querySelectorAll(selector)
– Lấy danh sách tất cả phần tử khớp với selector
-
Trả về danh sách NodeList chứa tất cả phần tử phù hợp.
Ví dụ:
<p class="text">Đoạn 1</p> <p class="text">Đoạn 2</p> <script> let paragraphs = document.querySelectorAll(".text"); console.log(paragraphs.length); // 2 </script>
Ứng dụng thực tế của DOM Navigation trong JavaScript
DOM Navigation không chỉ giúp truy xuất và thao tác các phần tử trong trang web mà còn hỗ trợ nhiều ứng dụng quan trọng trong lập trình JavaScript. Dưới đây là các ứng dụng thực tế phổ biến của DOM Navigation:
Thay đổi nội dung động (Dynamic Content)
Một trong những ứng dụng phổ biến nhất của DOM Navigation là thay đổi nội dung trang web mà không cần tải lại trang.
Ví dụ 1: Cập nhật nội dung khi bấm nút
Người dùng nhấn vào nút, nội dung đoạn văn sẽ thay đổi.
<p id="message">Chào bạn!</p> <button onclick="changeText()">Thay đổi nội dung</button> <script> function changeText() { let message = document.getElementById("message"); message.textContent = "Nội dung đã được cập nhật!"; } </script>
Giải thích: Khi bấm nút, JavaScript sẽ tìm đến phần tử có id="message"
và thay đổi nội dung của nó.
Ví dụ 2: Hiển thị thời gian thực tế trên trang web
<p id="time">Giờ hiện tại: </p> <button onclick="showTime()">Xem giờ</button> <script> function showTime() { let timeElement = document.getElementById("time"); let currentTime = new Date().toLocaleTimeString(); timeElement.textContent = "Giờ hiện tại: " + currentTime; } </script>
Giải thích: Khi bấm nút, JavaScript lấy thời gian hiện tại và cập nhật nội dung của phần tử <p>
.
Thay đổi giao diện trang web (CSS & Styles)
DOM Navigation cho phép thay đổi kiểu dáng của phần tử HTML bằng cách chỉnh sửa các thuộc tính CSS.
Ví dụ 1: Thay đổi màu nền của trang
<button onclick="changeBackground()">Đổi màu nền</button> <script> function changeBackground() { document.body.style.backgroundColor = "lightblue"; } </script>
Giải thích: Khi bấm nút, màu nền của toàn bộ trang web sẽ chuyển thành màu xanh nhạt.
Ví dụ 2: Ẩn và hiện một phần tử
<p id="text">Nội dung có thể ẩn/hiện</p> <button onclick="toggleVisibility()">Ẩn/Hiện</button> <script> function toggleVisibility() { let text = document.getElementById("text"); if (text.style.display === "none") { text.style.display = "block"; // Hiện phần tử } else { text.style.display = "none"; // Ẩn phần tử } } </script>
Giải thích: Khi bấm nút, nội dung sẽ bị ẩn hoặc hiển thị lại.
Thêm/xóa/sửa phần tử trong DOM
DOM Navigation giúp thêm, xóa hoặc chỉnh sửa các phần tử HTML động.
Ví dụ 1: Thêm phần tử vào danh sách
<ul id="list"> <li>Mục 1</li> <li>Mục 2</li> </ul> <button onclick="addItem()">Thêm mục</button> <script> function addItem() { let list = document.getElementById("list"); let newItem = document.createElement("li"); newItem.textContent = "Mục mới"; list.appendChild(newItem); } </script>
Giải thích: Khi bấm nút, một mục mới sẽ được thêm vào danh sách <ul>
.
Ví dụ 2: Xóa một phần tử khỏi danh sách
<ul id="list"> <li id="item1">Mục 1</li> <li>Mục 2</li> </ul> <button onclick="removeItem()">Xóa mục đầu</button> <script> function removeItem() { let list = document.getElementById("list"); let firstItem = list.firstElementChild; if (firstItem) { list.removeChild(firstItem); } } </script>
Giải thích: Khi bấm nút, mục đầu tiên trong danh sách sẽ bị xóa.
Ví dụ 3: Chỉnh sửa nội dung phần tử
<p id="paragraph">Đây là đoạn văn.</p> <button onclick="editText()">Chỉnh sửa</button> <script> function editText() { let paragraph = document.getElementById("paragraph"); paragraph.textContent = "Nội dung đã được chỉnh sửa!"; } </script>