Giới thiệu và thao tác với DOM trong JavaScript

1. Tổng quan về DOM

DOM (Document Object Model) là giao diện lập trình chuẩn do W3C đề xuất để xử lý các tài liệu HTML/XML. Qua DOM, ta có thể truy cập và thao tác với cấu trúc, nội dung và kiểu dáng của trang web.

  • Tài liệu (Document): Mỗi trang web là một tài liệu, được biểu diễn bằng đối tượng document.
  • Phần tử (Element): Các thẻ HTML là phần tử, được biểu diễn bằng đối tượng Element.
  • Nút (Node): Mọi thứ trong tài liệu (thẻ, thuộc tính, văn bản, chú thích...) đều là nút, được biểu diễn bằng Node.

Tất cả đều được xem như các đối tượng trong mô hình DOM.

2. Lấy phần tử trong DOM

2.1. Theo ID

const timerEl = document.getElementById('time');
console.log(timerEl);
console.dir(timerEl); // Xem chi tiết thuộc tính/phương thức

2.2. Theo tên thẻ

const listItems = document.getElementsByTagName('li');
console.log(listItems); // Trả về HTMLCollection (giống mảng)

// Duyệt qua từng phần tử
for (let i = 0; i < listItems.length; i++) {
  console.log(listItems[i]);
}

// Lấy phần tử con trong một phần tử cha cụ thể
const container = document.getElementById('ftl');
const childItems = container.getElementsByTagName('li');

2.3. Các phương pháp mới từ HTML5

// Theo class
const boxes = document.getElementsByClassName('box');

// Truy vấn CSS selector: trả về phần tử đầu tiên
const firstBox = document.querySelector('.box');

// Truy vấn tất cả phần tử khớp selector
const allBoxes = document.querySelectorAll('.box');

2.4. Truy cập thẻ đặc biệt

const body = document.body;
const html = document.documentElement;

3. Cơ bản về sự kiện (Event)

Sự kiện gồm 3 thành phần:

  • Nguồn sự kiện (Event target): Phần tử kích hoạt sự kiện.
  • Loại sự kiện (Event type): Ví dụ click, mouseover.
  • Hàm xử lý (Event handler): Hàm được gọi khi sự kiện xảy ra.
const btn = document.getElementById('btn');
btn.onclick = function() {
  alert('Đã nhấn nút!');
};

4. Thao tác nội dung phần tử

4.1. Thay đổi nội dung văn bản

const div = document.querySelector('div');
div.innerText = 'Nội dung thuần'; // Không hỗ trợ HTML
div.innerHTML = '<strong>Nội dung có HTML</strong>'; // Hỗ trợ HTML

4.2. Cập nhật theo thời gian thực

function getCurrentTime() {
  const now = new Date();
  const days = ['Chủ nhật', 'Thứ hai', 'Thứ ba', 'Thứ tư', 'Thứ năm', 'Thứ sáu', 'Thứ bảy'];
  return `Hôm nay là: ${now.getFullYear()} năm ${now.getMonth() + 1} tháng ${now.getDate()} ngày ${days[now.getDay()]}`;
}

const timeDiv = document.querySelector('div');
timeDiv.innerText = getCurrentTime();

5. Thao tác thuộc tính

5.1. Thuộc tính thông thường

const img = document.querySelector('img');
document.getElementById('zxy').onclick = () => {
  img.src = 'images/zxy.jpg';
  img.title = 'Trương Học Hữu';
};

5.2. Thuộc tính biểu mẫu

const input = document.querySelector('input');
const button = document.querySelector('button');

button.onclick = function() {
  input.value = 'Đã nhấn';
  this.disabled = true; // this trỏ đến button
};

5.3. Chuyển đổi loại input (password ↔ text)

const eyeIcon = document.getElementById('eye');
const pwdInput = document.getElementById('password');
let isRevealed = false;

eyeIcon.onclick = () => {
  if (!isRevealed) {
    pwdInput.type = 'text';
    eyeIcon.src = 'images/open.png';
  } else {
    pwdInput.type = 'password';
    eyeIcon.src = 'images/close.png';
  }
  isRevealed = !isRevealed;
};

6. Thao tác kiểu dáng (Style)

6.1. Qua thuộc tính style

const box = document.querySelector('div');
box.onclick = () => {
  box.style.backgroundColor = 'purple';
  box.style.width = '500px';
};

6.2. Qua class

const messageEl = document.querySelector('.message');
const passwordField = document.querySelector('#password');

passwordField.onblur = () => {
  const len = passwordField.value.length;
  if (len < 6 || len > 16) {
    messageEl.className = 'message wrong';
    messageEl.textContent = 'Mật khẩu phải từ 6–16 ký tự';
  } else {
    messageEl.className = 'message right';
    messageEl.textContent = 'Hợp lệ';
  }
};

7. Tư duy loại trừ (Exclusive Selection)

const buttons = document.querySelectorAll('button');
buttons.forEach(btn => {
  btn.onclick = function() {
    // Bỏ chọn tất cả
    buttons.forEach(b => b.style.backgroundColor = '');
    // Chọn chính mình
    this.style.backgroundColor = 'pink';
  };
});

8. Thuộc tính tùy chỉnh

8.1. Cách cổ điển

// Lấy
element.getAttribute('data-id');

// Đặt
element.setAttribute('data-role', 'admin');

// Xóa
element.removeAttribute('data-temp');

8.2. Chuẩn HTML5 (data-*)

// HTML: <div data-user-id="123"></div>
const el = document.querySelector('div');
console.log(el.dataset.userId); // "123"
el.dataset.status = 'active';

9. Thao tác nút (Node)

9.1. Duyệt theo cấp bậc

  • parentNode: Nút cha gần nhất.
  • children: Mảng chỉ chứa phần tử con (không có text node).
  • firstElementChild / lastElementChild: Phần tử con đầu/cuối.
  • nextElementSibling / previousElementSibling: Anh/chị em liền kề.

9.2. Tạo và chèn nút

const newItem = document.createElement('li');
newItem.textContent = 'Mới';
document.querySelector('ul').appendChild(newItem);

// Chèn trước phần tử khác
const ref = document.querySelector('li:first-child');
document.querySelector('ul').insertBefore(newItem, ref);

9.3. Xóa và sao chép

// Xóa
parent.removeChild(child);

// Sao chép (deep clone)
const clone = originalNode.cloneNode(true);

10. Sự kiện nâng cao

10.1. Đăng ký sự kiện

// Cách truyền thống (chỉ 1 handler)
btn.onclick = handler;

// EventListener (nhiều handler)
btn.addEventListener('click', handler1);
btn.addEventListener('click', handler2);

10.2. Gỡ bỏ sự kiện

// Truyền thống
btn.onclick = null;

// EventListener
btn.removeEventListener('click', handler);

10.3. Luồng sự kiện (Event Flow)

Gồm 3 pha: CaptureTargetBubble. Mặc định lắng nghe ở pha bubble.

element.addEventListener('click', handler, true); // Capture phase

10.4. Đối tượng sự kiện (Event Object)

  • e.target: Phần tử thực sự bị click.
  • this: Phần tử được gắn sự kiện.
  • e.type: Loại sự kiện (không có tiền tố on).

10.5. Ngăn hành vi mặc định và nổi bọt

// Ngăn chuyển trang
link.addEventListener('click', e => e.preventDefault());

// Ngăn nổi bọt
child.addEventListener('click', e => e.stopPropagation());

10.6. Ủy quyền sự kiện (Event Delegation)

document.querySelector('ul').addEventListener('click', e => {
  if (e.target.tagName === 'LI') {
    e.target.style.backgroundColor = 'pink';
  }
});

10.7. Sự kiện chuột và bàn phím

// Vô hiệu hóa chuột phải
document.addEventListener('contextmenu', e => e.preventDefault());

// Sự kiện bàn phím
input.addEventListener('keydown', e => {
  console.log('Phím nhấn:', e.key, 'Mã ASCII:', e.keyCode);
});

Thẻ: JavaScript DOM HTML5 Event Handling Web Development

Đăng vào ngày 20 tháng 5 lúc 01:30