Bài 9: JavaScript — thao tác DOM (đổi nội dung, ẩn/hiện, tạo phần tử)

Bài 8 bạn đã làm nút bấm đổi nội dung bằng textContent. Bài này đi sâu hơn vào DOM — cách JavaScript “chạm” vào mọi phần tử trên trang để chọn, đổi nội dung, đổi kiểu, ẩn/hiện, và tạo phần tử mới. Cuối bài bạn sẽ làm một danh sách việc cần làm (to-do) tương tác: gõ việc, bấm Thêm, và việc hiện ra ngay trên trang.
⏱️ Cách học bài này (~30 phút): đọc cách chọn & thao tác phần tử (12’), tự gõ và bấm thử (12’), lưu file mang về (6’).
Mục tiêu bài học
Sau bài này bạn sẽ:
- Hiểu DOM là gì và chọn phần tử bằng
querySelector. - Đổi nội dung (
textContent) và kiểu (style,classList). - Ẩn/hiện phần tử bằng
style.display. - Tạo và thêm phần tử mới (
createElement,appendChild).
Nội dung: thao tác DOM
1. DOM là gì
Khi trình duyệt tải HTML, nó dựng trang thành một cây phần tử gọi là DOM. JavaScript đọc và thay đổi cây này để cập nhật trang ngay lập tức — không cần tải lại.
2. Chọn phần tử
const tieuDe = document.querySelector("#tieu-de"); // theo id (#)
const cacMuc = document.querySelectorAll(".muc"); // theo class (.), trả về nhiều
querySelector nhận cú pháp CSS: #id, .class, hay tên thẻ. Nó trả về phần tử đầu tiên khớp; querySelectorAll trả về tất cả (một danh sách phải lặp qua):
cacMuc.forEach(function (muc) { // lặp qua từng phần tử khớp
muc.style.color = "green"; // đổi màu tất cả .muc
});
3. Đổi nội dung và kiểu
tieuDe.textContent = "Danh sách của tôi"; // đổi chữ
tieuDe.style.color = "blue"; // đổi màu chữ
tieuDe.classList.add("noi-bat"); // thêm class CSS
tieuDe.classList.remove("noi-bat"); // bỏ class
tieuDe.classList.toggle("noi-bat"); // có thì bỏ, không thì thêm
classList.toggle rất tiện để bật/tắt một trạng thái (ví dụ chế độ nổi bật).
4. Ẩn / hiện phần tử
const hop = document.querySelector("#hop");
hop.style.display = "none"; // ẩn
hop.style.display = "block"; // hiện lại
Đây chính là cách làm nút “Hiện/ẩn” mà Bài 8 còn để dành.
5. Tạo và thêm phần tử mới
const ds = document.querySelector("#danh-sach");
const muc = document.createElement("li"); // tạo thẻ <li>
muc.textContent = "Việc mới"; // đặt nội dung
ds.appendChild(muc); // thêm vào cuối danh sách
Code mẫu có chú thích: danh sách việc cần làm
HTML (trong <body>, có <script src="script.js"></script> trước </body>):
<input id="o-nhap" placeholder="Nhập việc cần làm">
<button id="nut-them">Thêm</button>
<ul id="danh-sach"></ul>
script.js:
const oNhap = document.querySelector("#o-nhap");
const nutThem = document.querySelector("#nut-them");
const danhSach = document.querySelector("#danh-sach");
nutThem.addEventListener("click", function () {
const viec = oNhap.value.trim(); // lấy chữ người dùng gõ, bỏ khoảng trắng thừa
if (viec === "") return; // rỗng thì không thêm
const muc = document.createElement("li"); // tạo <li> mới
muc.textContent = viec; // đặt nội dung
danhSach.appendChild(muc); // thêm vào danh sách
oNhap.value = ""; // xoá ô nhập cho lần sau
});
Cách chạy: lưu file, mở trang, gõ một việc rồi bấm Thêm — việc hiện ra thành một dòng trong danh sách. Gõ tiếp và bấm — danh sách dài thêm.
Bài thực hành code (tự gõ)
Bài 1 — Đổi kiểu: chọn tiêu đề trang bằng querySelector và đổi style.color sang màu bạn thích.
Bài 2 — Ẩn/hiện: thêm một nút; khi bấm, dùng classList.toggle hoặc style.display để ẩn/hiện một đoạn văn.
Bài 3 — Thêm phần tử: làm lại danh sách to-do ở trên; kiểm tra rằng ô nhập rỗng thì không thêm dòng trống.
Lỗi thường gặp & cách sửa
nullkhi querySelector → sai selector (thiếu#cho id,.cho class) hoặc<script>chạy trước khi HTML tải. Đặt<script>trước</body>.- Quên
.valuekhi lấy chữ từ ô<input>→ nhớ dùngoNhap.value, không phảioNhap.textContent. - Thêm dòng trống → kiểm tra rỗng bằng
if (viec === "") return;trước khi tạo phần tử. - Nhầm
classList.addvớiclass→ dùngelement.classList.add("ten"), không gán thẳngelement.class. - Đưa dữ liệu người dùng vào
innerHTML→ rủi ro bảo mật. Với chữ thường, dùngtextContent.
💾 Mang về — bộ thao tác DOM cơ bản
Lưu lại làm nền cho mọi trang tương tác:
// Chọn phần tử
const el = document.querySelector("#id-cua-ban");
// Đổi nội dung & kiểu
el.textContent = "Nội dung mới";
el.classList.toggle("noi-bat");
// Ẩn / hiện
el.style.display = "none"; // hoặc "block" để hiện
// Tạo & thêm phần tử
const moi = document.createElement("li");
moi.textContent = "Mục mới";
document.querySelector("#danh-sach").appendChild(moi);
Thuật ngữ chốt
| Thuật ngữ | Giải thích ngắn |
|---|---|
| DOM | Cây phần tử của trang mà JS đọc/sửa được |
querySelector |
Chọn 1 phần tử theo cú pháp CSS (#id, .class) |
querySelectorAll |
Chọn tất cả phần tử khớp |
textContent |
Nội dung chữ thuần của phần tử |
classList |
Thêm/bỏ/bật-tắt class CSS (add/remove/toggle) |
style.display |
"none" để ẩn, "block" để hiện |
createElement / appendChild |
Tạo phần tử mới / thêm vào trang |
.value |
Giá trị chữ trong ô <input> |
Tự kiểm tra
- Chọn phần tử theo class
.itemdùng gì? (Đáp án:querySelector(".item")hoặcquerySelectorAll) - Ẩn một phần tử bằng cách nào? (Đáp án:
element.style.display = "none") - Lấy chữ người dùng gõ trong
<input>dùng gì? (Đáp án:element.value)
Ghi nhớ nhanh
- Chọn:
querySelector("#id" / ".class"); nhiều phần tử:querySelectorAll. - Đổi:
textContent(chữ),style(kiểu),classList.add/remove/toggle(class). - Ẩn/hiện:
style.display = "none" / "block". - Thêm mới:
createElement→textContent→appendChild.
Bài tập về nhà: thêm nút “Xoá” cho mỗi việc trong danh sách to-do (gợi ý: tạo một <button> bên trong <li>, gắn addEventListener gọi muc.remove()). Bài tiếp theo: Bài 10 — Dự án: hoàn thiện trang cá nhân (sắp đăng).
Câu hỏi thường gặp
DOM trong JavaScript là gì?
DOM (Document Object Model) là cách trình duyệt biểu diễn trang HTML thành một ‘cây’ các phần tử mà JavaScript có thể đọc và thay đổi. Nhờ DOM, code JS của bạn có thể tìm một thẻ, đổi nội dung, đổi màu, ẩn/hiện hay thêm phần tử mới — tức là thay đổi trang ngay sau khi tải mà không cần load lại. Đây là nền tảng của mọi trang web tương tác.
getElementById và querySelector khác nhau thế nào?
Cả hai đều để chọn phần tử. getElementById(‘nut’) chỉ chọn theo id và trả về đúng một phần tử. querySelector(‘…’) linh hoạt hơn: nó nhận cú pháp CSS, nên bạn chọn theo id (#nut), theo class (.item) hay theo thẻ (p) đều được, và trả về phần tử ĐẦU TIÊN khớp. Muốn chọn NHIỀU phần tử cùng lúc thì dùng querySelectorAll.
textContent và innerHTML khác nhau ở điểm nào?
textContent đặt/đọc nội dung dưới dạng CHỮ thuần — an toàn và nên dùng mặc định. innerHTML đặt/đọc nội dung dưới dạng HTML, nên có thể chèn cả thẻ (ví dụ thêm <b>). Cẩn thận: đừng đưa dữ liệu do người dùng nhập thẳng vào innerHTML vì có thể tạo lỗ hổng bảo mật (XSS); với chữ thường, hãy ưu tiên textContent.
Phù thủy bàn phím, mê tự động hoá và 'lười thông minh'. Gom phần mềm, code và AI thành mấy phép nhỏ giúp bạn xong việc trước giờ nghỉ trưa.
Bài liên quan

Bài 10: Đọc và ghi file trong Python
Bài 10 series Python cho người mới (bài học 30 phút): đọc và ghi file văn bản — lưu dữ liệu ra file, đọc lại, ghi thêm — dùng with open và encoding UTF-8 cho tiếng Việt; kèm bài tập và code mang về.

Bài 8: JavaScript — biến, hàm và sự kiện
Bài 8 series Web cơ bản (bài học 30 phút): thêm tương tác cho trang bằng JavaScript — biến, hàm và sự kiện click — làm một nút bấm đổi nội dung trang; kèm thực hành và file mang về.

Bài 9: Xử lý lỗi với try/except trong Python
Bài 9 series Python cho người mới (bài học 30 phút): dùng try/except để chương trình không sập khi gặp lỗi — bắt lỗi nhập liệu, báo lỗi thân thiện — qua chương trình nhập số an toàn; kèm bài tập và code mang về.