Tìm hiểu HTML và truy cập DOM trong JavaScript
← Quay lại trang chínhTrước khi tìm hiểu về DOM, chúng ta cần hiểu rõ một website được xây dựng từ những thành phần nào và chúng hoạt động ra sao.
Vai trò: Xây dựng khung xương và nội dung của trang web
<h1>Tiêu đề</h1>, <p>Đoạn văn</p>
Vai trò: Tạo giao diện đẹp và bố cục cho website
color: blue;, font-size: 18px;
Vai trò: Thêm tính tương tác và xử lý logic
button.addEventListener('click', ...)
Để hiểu rõ hơn, hãy tưởng tượng website như một ngôi nhà:
Thiếu HTML → không có nhà. Thiếu CSS → nhà xấu. Thiếu JavaScript → nhà "câm".
Sau khi hiểu website gồm HTML-CSS-JavaScript, giờ chúng ta tìm hiểu DOM - cầu nối quan trọng giữa HTML và JavaScript.
DOM là mô hình đối tượng tài liệu - một cách biểu diễn cấu trúc HTML dưới dạng cây đối tượng mà JavaScript có thể hiểu và thao tác.
DOM biến HTML thành một cây phân cấp, mỗi thẻ HTML trở thành một node (nút):
JavaScript không thể:
JavaScript có thể:
Click nút bên dưới để xem JavaScript thay đổi HTML thông qua DOM:
Đây là đoạn text ban đầu.
Sau khi hiểu DOM và ID/Class, giờ chúng ta tìm hiểu chi tiết về HTML (HyperText Markup Language) - ngôn ngữ đánh dấu để xây dựng cấu trúc và nội dung trang web.
<tagname>nội dung</tagname><!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tiêu đề trang</title>
</head>
<body>
<!-- Nội dung website ở đây -->
<h1>Xin chào thế giới!</h1>
<p>Đây là trang web đầu tiên của tôi.</p>
</body>
</html>
<!DOCTYPE html> - Khai báo đây là HTML5<html> - Thẻ gốc chứa toàn bộ trang<head> - Thông tin meta (không hiển thị)<body> - Nội dung hiển thị trên trang<h1>Tiêu đề cấp 1 - Quan trọng nhất</h1>
<h2>Tiêu đề cấp 2 - Phần chính</h2>
<h3>Tiêu đề cấp 3 - Tiểu mục</h3>
<h4>Tiêu đề cấp 4</h4>
<h5>Tiêu đề cấp 5</h5>
<h6>Tiêu đề cấp 6 - Nhỏ nhất</h6>
<p>Đây là một đoạn văn bình thường.</p>
<p>Đoạn văn có thể chứa <strong>text đậm</strong> và <em>text nghiêng</em>.</p>
<!-- Thẻ ngắt dòng và đường kẻ ngang -->
<p>Dòng này<br>có ngắt dòng ở giữa.</p>
<hr>
<p>Đoạn này sau đường kẻ ngang.</p>
<!-- Thẻ định dạng khác -->
<p>
<mark>Text được highlight</mark><br>
<small>Text nhỏ</small><br>
<del>Text bị gạch xóa</del><br>
<ins>Text được thêm vào</ins>
</p>
Đây là một đoạn văn bình thường.
Đoạn văn có thể chứa text đậm và text nghiêng.
Dòng này
có ngắt dòng ở giữa.
Đoạn này sau đường kẻ ngang.
Text được highlight
Text nhỏ
Text bị gạch xóa
Text được thêm vào
<!-- DIV: Block element -->
<div style="background: #e3f2fd; padding: 15px; margin: 10px 0; border-radius: 5px;">
<h4>Khối DIV 1</h4>
<p>Đây là nội dung trong div. DIV chiếm toàn bộ chiều rộng.</p>
</div>
<div style="background: #e8f5e8; padding: 15px; margin: 10px 0; border-radius: 5px;">
<h4>Khối DIV 2</h4>
<p>Div khác sẽ xuống dòng mới.</p>
</div>
<!-- SPAN: Inline element -->
<p>
Trong câu này có <span style="color: red; background: #ffe6e6;">span màu đỏ</span>
và <span style="color: blue; background: #e6f2ff;">span màu xanh</span>
trên cùng một dòng.
</p>
Đây là nội dung trong div. DIV chiếm toàn bộ chiều rộng.
Div khác sẽ xuống dòng mới.
Trong câu này có span màu đỏ và span màu xanh trên cùng một dòng.
<!-- Liên kết đến website khác -->
<a href="https://www.google.com">Đi tới Google</a>
<!-- Mở tab mới -->
<a href="https://www.youtube.com" target="_blank">Mở YouTube tab mới</a>
<!-- Liên kết email -->
<a href="mailto:someone@example.com">Gửi Email</a>
<!-- Liên kết phone -->
<a href="tel:+84123456789">Gọi điện: 0123456789</a>
<!-- Liên kết trong trang (anchor) -->
<a href="#top">Lên đầu trang</a>
<a href="#footer">Xuống cuối trang</a>
<!-- Liên kết tải file -->
<a href="document.pdf" download>Tải PDF</a>
<!-- Hình ảnh cơ bản -->
<img src="https://via.placeholder.com/300x200/4facfe/ffffff?text=Demo+Image"
alt="Hình ảnh demo">
<!-- Với kích thước tùy chỉnh -->
<img src="https://via.placeholder.com/150x100/28a745/ffffff?text=Small"
alt="Hình nhỏ"
width="150"
height="100">
<!-- Với style CSS -->
<img src="https://via.placeholder.com/200x150/e53e3e/ffffff?text=Rounded"
alt="Hình bo góc"
style="border-radius: 15px; border: 3px solid #ddd;">
<!-- Hình responsive -->
<img src="https://via.placeholder.com/400x250/9c27b0/ffffff?text=Responsive"
alt="Hình responsive"
style="max-width: 100%; height: auto; border-radius: 8px;">
<!-- Danh sách không có thứ tự (Unordered List) -->
<ul>
<li>Mục 1: HTML cơ bản</li>
<li>Mục 2: CSS styling</li>
<li>Mục 3: JavaScript
<ul>
<li>DOM manipulation</li>
<li>Event handling</li>
<li>AJAX requests</li>
</ul>
</li>
<li>Mục 4: Frameworks</li>
</ul>
<!-- Danh sách có thứ tự (Ordered List) -->
<ol>
<li>Bước 1: Phân tích yêu cầu</li>
<li>Bước 2: Thiết kế wireframe</li>
<li>Bước 3: Viết HTML</li>
<li>Bước 4: Style với CSS</li>
<li>Bước 5: Thêm JavaScript</li>
<li>Bước 6: Test và deploy</li>
</ol>
<!-- Danh sách định nghĩa (Description List) -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language - ngôn ngữ đánh dấu siêu văn bản</dd>
<dt>CSS</dt>
<dd>Cascading Style Sheets - bảng định dạng theo tầng</dd>
<dt>JavaScript</dt>
<dd>Ngôn ngữ lập trình để tạo tính tương tác cho website</dd>
</dl>
<form>
<!-- Text inputs -->
<label for="username">Tên đăng nhập:</label>
<input type="text" id="username" name="username" placeholder="Nhập tên...">
<label for="email">Email:</label>
<input type="email" id="email" name="email" placeholder="email@example.com">
<label for="password">Mật khẩu:</label>
<input type="password" id="password" name="password">
<!-- Number and date -->
<label for="age">Tuổi:</label>
<input type="number" id="age" name="age" min="1" max="120">
<label for="birthday">Ngày sinh:</label>
<input type="date" id="birthday" name="birthday">
<!-- Textarea -->
<label for="message">Tin nhắn:</label>
<textarea id="message" name="message" rows="4" placeholder="Nhập tin nhắn..."></textarea>
<!-- Checkboxes -->
<p>Sở thích:</p>
<input type="checkbox" id="music" name="hobby" value="music">
<label for="music">Âm nhạc</label>
<input type="checkbox" id="sports" name="hobby" value="sports">
<label for="sports">Thể thao</label>
<!-- Radio buttons -->
<p>Giới tính:</p>
<input type="radio" id="male" name="gender" value="male">
<label for="male">Nam</label>
<input type="radio" id="female" name="gender" value="female">
<label for="female">Nữ</label>
<!-- Select dropdown -->
<label for="country">Quốc gia:</label>
<select id="country" name="country">
<option value="">Chọn quốc gia...</option>
<option value="vn">Việt Nam</option>
<option value="us">Hoa Kỳ</option>
<option value="jp">Nhật Bản</option>
</select>
<!-- Buttons -->
<button type="submit">Gửi form</button>
<button type="reset">Reset</button>
<button type="button">Button thường</button>
</form>
<!DOCTYPE html>
<html>
<head>
<title>Semantic HTML5</title>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="#home">Trang chủ</a></li>
<li><a href="#about">Giới thiệu</a></li>
<li><a href="#contact">Liên hệ</a></li>
</ul>
</nav>
</header>
<main>
<section id="hero">
<h1>Chào mừng đến website</h1>
<p>Mô tả ngắn về website...</p>
</section>
<section id="content">
<article>
<header>
<h2>Tiêu đề bài viết</h2>
<time datetime="2024-01-15">15 tháng 1, 2024</time>
</header>
<p>Nội dung bài viết...</p>
<footer>
<p>Tác giả: John Doe</p>
</footer>
</article>
</section>
<aside>
<h3>Sidebar</h3>
<p>Nội dung phụ, quảng cáo, links liên quan...</p>
</aside>
</main>
<footer>
<p>© 2024 Website Name. All rights reserved.</p>
</footer>
</body>
</html>
Thử nghiệm với các thẻ HTML đã học:
Click nút phía trên để xem demo các thẻ HTML
Để làm việc với DOM, điều đầu tiên chúng ta cần biết là cách truy cập các phần tử HTML từ JavaScript.
Mục đích: Tìm 1 phần tử duy nhất theo thuộc tính id
Sử dụng khi: Cần truy cập phần tử cụ thể, quan trọng (form, title, button chính...)
// Lấy phần tử theo ID
const title = document.getElementById('demoTitle');
const input = document.getElementById('demoInput');
const button = document.getElementById('demoButton');
// Đọc nội dung
console.log('Tiêu đề:', title.textContent);
console.log('Giá trị input:', input.value);
getElementById() trả về: Một object HTMLElement duy nhất (hoặc null nếu không tìm thấy)
title.tagName → "H2"title.id → "demoTitle"title.textContent → "Nội dung tiêu đề"title.innerHTML → "Nội dung tiêu đề"title.className → "" (nếu không có class)title.style → CSSStyleDeclaration objecttitle.parentElement → Element chatitle.children → HTMLCollection các element con
input.tagName → "INPUT"input.type → "text"input.value → "giá trị người dùng nhập"input.placeholder → "📝 Nhập dữ liệu..."input.disabled → falseinput.checked → undefined (chỉ có với checkbox/radio)
button.tagName → "BUTTON"button.type → "button"button.textContent → "🚀 Nút demo"button.disabled → falsebutton.onclick → function hoặc null
Mục đích: Tìm nhiều phần tử có cùng class name
Sử dụng khi: Thao tác với nhóm phần tử giống nhau (danh sách sản phẩm, card, button...)
// Lấy tất cả phần tử có class 'list-item'
const listItems = document.getElementsByClassName('list-item');
// Kết quả là HTMLCollection (giống array)
console.log('Số lượng items:', listItems.length);
// Duyệt qua từng phần tử
for (let i = 0; i < listItems.length; i++) {
console.log('Item', i + 1, ':', listItems[i].textContent);
}
getElementsByClassName() trả về: HTMLCollection - một danh sách "sống" (live collection)
listItems.length → 3 (số phần tử)listItems[0] → HTMLElement đầu tiênlistItems[1] → HTMLElement thứ 2listItems.item(0) → Tương tự [0]listItems.namedItem('id') → Tìm theo ID (nếu có)
listItems[0].tagName → "LI"listItems[0].textContent → "📋 Mục danh sách 1"listItems[0].className → "list-item"listItems[0].parentElement → UL element chứa nó
Mục đích: Truy vấn phần tử bằng CSS selector (linh hoạt nhất)
Sử dụng khi: Cần truy vấn phức tạp, kết hợp nhiều điều kiện
// querySelector: Lấy phần tử đầu tiên
const firstListItem = document.querySelector('.list-item');
const demoBox = document.querySelector('.demo-box');
// querySelectorAll: Lấy tất cả phần tử
const allListItems = document.querySelectorAll('.list-item');
const allButtons = document.querySelectorAll('button');
// CSS selector nâng cao
const firstLi = document.querySelector('ul li:first-child');
const inputText = document.querySelector('input[type="text"]');
console.log('First item:', firstListItem.textContent);
console.log('Tất cả buttons:', allButtons.length);
Trả về: HTMLElement đầu tiên tìm thấy (hoặc null)
element.tagName → "DIV"element.className → "demo-box"element.textContent → nội dungelement.style → CSSStyleDeclaration
Trả về: NodeList - danh sách "tĩnh" (static)
nodeList.length → số phần tửnodeList[0] → element đầu tiênnodeList.forEach() → có thể dùng!nodeList.item(0) → tương tự [0]
Mọi HTML Element đều có những thuộc tính cơ bản này. Dưới đây là cú pháp và kết quả trả về:
input.value - Giá trị nhậpinput.type - Loại inputinput.placeholder - Text gợi ýinput.checked - Trạng thái checkinput.disabled - Có bị vô hiệu hóainput.required - Có bắt buộcinput.maxLength - Độ dài tối đa
link.href - Đường dẫn URLlink.target - Cách mở (_blank...)link.download - Tên file tảilink.rel - Quan hệ (nofollow...)link.hostname - Tên domainlink.pathname - Đường dẫnlink.search - Query parameters
img.src - Đường dẫn ảnhimg.alt - Text thay thếimg.width - Chiều rộngimg.height - Chiều caoimg.naturalWidth - Chiều rộng gốcimg.naturalHeight - Chiều cao gốcimg.complete - Đã load xong?
form.action - URL gửi formform.method - GET hoặc POSTform.elements - Tất cả controlsselect.selectedIndex - Option được chọnselect.options - Danh sách optionstextarea.rows - Số dòngtextarea.cols - Số cột
Thử các phương thức truy cập DOM với HTML demo phía trên ⬆️
Trước khi học cách truy cập DOM, chúng ta cần hiểu ID và Class - hai cách quan trọng để "đặt tên" và "phân loại" các phần tử HTML.
<!-- ✅ Đúng: Mỗi ID chỉ dùng 1 lần -->
<header id="mainHeader">Header chính</header>
<nav id="primaryNav">Menu điều hướng</nav>
<form id="loginForm">Form đăng nhập</form>
<button id="submitBtn">Gửi</button>
<footer id="siteFooter">Footer</footer>
<!-- ❌ Sai: Không được trùng ID -->
<div id="content">Nội dung 1</div>
<div id="content">Nội dung 2</div> <!-- Sai! -->
<!-- ✅ Đúng: Nhiều phần tử cùng class -->
<button class="btn">Lưu</button>
<button class="btn">Hủy</button>
<button class="btn">Xóa</button>
<!-- ✅ Đúng: Một phần tử nhiều class -->
<button class="btn btn-primary">Button chính</button>
<button class="btn btn-secondary">Button phụ</button>
<!-- ✅ Đúng: Danh sách cùng class -->
<div class="product-card">Sản phẩm 1</div>
<div class="product-card">Sản phẩm 2</div>
<div class="product-card">Sản phẩm 3</div>
| Tiêu chí | 🆔 ID | 🎯 Class |
|---|---|---|
| Số lượng | 1 ID / trang | Không giới hạn |
| Tái sử dụng | ❌ Không | ✅ Có |
| CSS Selector | #idName |
.className |
| JS Method | getElementById() |
getElementsByClassName() |
| Ưu tiên CSS | Cao | Thấp hơn |
| Tốc độ truy cập | Nhanh nhất | Nhanh |
Quan sát HTML demo bên dưới để hiểu cách sử dụng ID và Class: