Giới thiệu về DOM và BOM
DOM (Mô hình Đối tượng Tài liệu)
Định nghĩa: Giao diện lập trình giúp chuyển đổi tài liệu HTML/XML thành cấu trúc cây, cho phép JavaScript thao tác nội dung trang web.
Cấu trúc chính
graph TD A[Document] --> B[Element: html] B --> C[Element: head] B --> D[Element: body] C --> E[Element: title] C --> F[Element: meta] D --> G[Element: div] D --> H[Element: p] D --> I[Element: script] G --> J[Text: Hello] H --> K[Text: World]
Loại nút chính
| Loại | Mô tả | Ví dụ |
|---|---|---|
| Document | Điểm bắt đầu của toàn bộ tài liệu | `document` |
| Element | Phần tử HTML | ` `, ` ` |
| Attr | Thuộc tính phần tử | `class="container"` |
| Text | Nút văn bản | `Hello World` |
| Comment | Nút chú thích | `` |
Các API phổ biến
// Truy vấn phần tử
document.querySelector('#mainHeader')
document.querySelectorAll('.card')
// Thay đổi nội dung
node.innerText = 'Nội dung mới'
node.innerHTML = '<span>Nội dung</span>'
// Điều chỉnh kiểu
node.style.backgroundColor = '#f0f0f0'
node.classList.toggle('highlight')
// Xử lý sự kiện
button.addEventListener('click', () => {
alert('Bạn đã nhấp!')
})
BOM (Mô hình Đối tượng Trình duyệt)
Định nghĩa: Tập hợp API giúp JavaScript tương tác với cửa sổ trình duyệt, không có tiêu chuẩn chính thức nhưng được hỗ trợ rộng rãi.
Các đối tượng chính
graph LR W[window] --> N[navigator] W --> L[location] W --> H[history] W --> S[screen] W --> C[console] W --> X[XMLHttpRequest] W --> T[setTimeout]
Tính năng chính của các đối tượng
| Đối tượng | Mục đích | Ví dụ |
|---|---|---|
| window | Đối tượng cấp cao nhất của cửa sổ trình duyệt | `window.screenY` |
| navigator | Thông tin trình duyệt | `navigator.platform` |
| location | Xử lý URL và điều hướng | `location.reload()` |
| history | Quản lý lịch sử trang | `history.forward()` |
| screen | Thông tin màn hình người dùng | `screen.height` |
| console | Gỡ lỗi và in thông báo | `console.warn()` |
| sessionStorage | Lưu trữ tạm thời | `sessionStorage.setItem()` |
Các API thường dùng
// Điều hướng
location.replace('https://example.com')
history.pushState(null, '', '/profile')
// Điều khiển cửa sổ
window.open('popup.html', '_blank', 'width=400,height=300')
// Đếm ngược
const countdown = setInterval(() => {
console.log('Đếm ngược');
}, 1000)
// Lưu trữ dữ liệu
sessionStorage.setItem('language', 'vi')
const lang = sessionStorage.getItem('language')
So sánh DOM vs BOM
| Tính năng | DOM | BOM |
|---|---|---|
| Chuẩn | W3C chính thức | Không có chuẩn chính thức |
| Đối tượng tác động | Tài liệu | Cửa sổ trình duyệt |
| Đối tượng chính | Document, Element, Node | Window, Navigator, Location |
| Mục đích chính | Thao tác nội dung trang | Quản lý hành vi trình duyệt |
| Ví dụ | Thay đổi văn bản, giao diện | Điều hướng, lưu trữ, định thời |
| Mối quan hệ | Dựa vào BOM | Tự lập |
Trường hợp tương tác điển hình
- DOM kích hoạt BOM:
document.querySelector('#submitBtn').addEventListener('click', () => { window.location.href = '/dashboard'; // BOM }) - BOM ảnh hưởng DOM:
window.addEventListener('resize', () => { const width = window.innerWidth; // BOM document.body.style.margin = width > 1024 ? '4rem' : '2rem'; // DOM }) - Ví dụ kết hợp:
document.querySelector('form').addEventListener('submit', (e) => { e.preventDefault(); const formData = new FormData(e.target); // DOM localStorage.setItem('userSettings', JSON.stringify(formData)); // BOM window.history.go(-1); // BOM })
Tối ưu hiệu suất
- Tối ưu DOM:
const container = document.createDocumentFragment(); for (let i = 0; i < 50; i++) { const item = document.createElement('li'); item.textContent = `Mục ${i+1}`; container.appendChild(item); } document.getElementById('list').appendChild(container); - Lưu ý BOM:
// Sai lầm const largeData = localStorage.getItem('bigFile'); // Đúng cách setTimeout(() => { const largeData = localStorage.getItem('bigFile'); }, 0); - API hiện đại:
function animate() { node.style.transform = `translateX(${pos}px)`; if (pos < 200) requestAnimationFrame(animate); } requestAnimationFrame(animate);
Nguyên tắc vàng: Thao tác DOM là nguyên nhân chính gây chậm hiệu suất. Mỗi lần layout reflow đều tốn chi phí tính toán. Nên giảm thiểu thao tác DOM trực tiếp, ưu tiên sử dụng DocumentFragment, thư viện virtual DOM. Với BOM, cần chú ý rủi ro bị chặn bởi các API đồng bộ như localStorage khi xử lý dữ liệu lớn.