JavaHướng dẫn Script DOM với Ví dụ
⚡ Tóm tắt thông minh
JavaScript DOM và Events cho phép các script kiểm soát hoàn toàn một trang web, cho phép mã đọc, thay đổi, thêm hoặc xóa bất kỳ phần tử nào mà trình duyệt hiển thị, sau đó phản hồi ngay lập tức mỗi khi khách truy cập nhấp chuột, nhập liệu hoặc cuộn trang.

DOM trong đó là gì JavaKịch bản?
JavaScript có thể truy cập tất cả các phần tử trong một trang web bằng cách sử dụng Mô hình Đối tượng Tài liệu (DOM). Trên thực tế, trình duyệt web tạo ra DOM của trang web khi trang được tải. Mô hình DOM được tạo ra dưới dạng cây các đối tượng như sau:
Mỗi phần tử HTML trên một trang trở thành một nút bên trong cây DOM này. Trình duyệt nhóm các nút DOM thành một vài loại cốt lõi: các nút phần tử đại diện cho các thẻ như... <p> or <div>Các nút văn bản chứa các từ hiển thị bên trong thẻ, các nút thuộc tính lưu trữ các giá trị như... id or classvà các nút bình luận giữ nguyên <!-- --> đánh dấu. Nút trên cùng luôn là document Đối tượng này, và mọi phần tử khác đều là hậu duệ của nó.
Sử dụng DOM, JavaScript Nó có thể thực hiện nhiều tác vụ. Nó có thể tạo các phần tử và thuộc tính mới, thay đổi các phần tử và thuộc tính hiện có, và thậm chí xóa các phần tử và thuộc tính hiện có. JavaScript cũng có thể phản ứng với các sự kiện hiện có và tạo ra các sự kiện mới trên trang. Các phần bên dưới sẽ hướng dẫn cách chọn các phần tử, chỉnh sửa chúng và kết nối các trình xử lý sự kiện với các ví dụ thực tế, có thể chạy được.
Cần nhớ rằng DOM không giống với tệp nguồn HTML. HTML mà trình duyệt tải xuống là văn bản tĩnh, nhưng DOM mà nó xây dựng từ văn bản đó là một mô hình đối tượng động, sống động. Bất kỳ thay đổi nào cũng có thể ảnh hưởng đến DOM. JavaĐoạn mã này giúp nội dung hiển thị trên màn hình ngay lập tức sau khi được chỉnh sửa từ DOM, mà không cần thay đổi tệp HTML gốc.
Cách chọn các phần tử DOM trong JavaScript
Trước JavaScript có thể thay đổi bất cứ thứ gì trên trang, trước tiên nó cần chọn nút mục tiêu. DOM cung cấp một số phương thức chọn, mỗi phương thức phù hợp với các tình huống khác nhau:
- getElementById(): Trả về phần tử duy nhất khớp với điều kiện đã cho.
idthuộc tính. - getElementsByClassName(): Trả về một HTMLCollection động chứa mọi phần tử mang lớp được chỉ định.
- getElementsByTagName(): Trả về một HTMLCollection trực tiếp chứa mọi phần tử có tên thẻ nhất định, ví dụ như:
porli. - truy vấnSelector(): Trả về phần tử đầu tiên khớp với bất kỳ bộ chọn CSS nào.
- querySelectorAll(): Trả về một NodeList tĩnh chứa mọi phần tử khớp với bộ chọn CSS.
Bảng dưới đây so sánh bốn phương pháp tuyển chọn được sử dụng phổ biến nhất để bạn có thể chọn phương pháp phù hợp nhất cho công việc.
| Phương pháp | Hoàn trả | Sử dụng tốt nhất khi |
|---|---|---|
| Getelementbyid | Thành phần đơn lẻ | Bạn biết chính xác mã định danh duy nhất của mục tiêu. |
| getElementsByClassName | Bộ sưu tập HTML trực tiếp | Bạn cần tất cả các phần tử đều có cùng tên lớp. |
| bộ chọn truy vấn | Phần tử đơn (kết quả khớp đầu tiên) | Bạn nên sử dụng bất kỳ bộ chọn CSS nào, không chỉ id hoặc class. |
| truy vấnSelectorAll | Danh sách nút tĩnh | Bạn cần lặp qua từng kết quả khớp bằng vòng lặp forEach. |
`querySelector` và `querySelectorAll` chấp nhận bất kỳ bộ chọn CSS hợp lệ nào, điều này khiến chúng trở thành lựa chọn linh hoạt nhất cho mã hiện đại. Hãy thử đoạn mã bên dưới trong một trang có chứa phần tử `<div>` với `<div>`. id="title" và một số yếu tố với class="item":
const heading = document.getElementById("title"); const itemsByClass = document.getElementsByClassName("item"); const firstItem = document.querySelector(".item"); const allItems = document.querySelectorAll(".item"); console.log(heading.textContent, itemsByClass.length, allItems.length);
getElementById và getElementsByClassName vẫn nhanh hơn đối với các tìm kiếm đơn giản, trong khi querySelector và querySelectorAll được ưu tiên sử dụng khi logic lựa chọn cần đến sức mạnh của cú pháp CSS đầy đủ, chẳng hạn như bộ chọn thuộc tính hoặc bộ chọn hậu duệ.
Cách chỉnh sửa, tạo và xóa các phần tử DOM
Sau khi một phần tử được chọn, JavaScript có thể đọc hoặc ghi đè nội dung, thuộc tính, và thậm chí cả sự tồn tại của nó trong cây DOM. Sử dụng DOM, JavaScript có thể tạo các phần tử và thuộc tính mới, thay đổi các phần tử và thuộc tính hiện có, và xóa hoàn toàn các phần tử và thuộc tính hiện có.
Thay đổi nội dung bằng getElementById và innerHTML
- getElementById: Để truy cập các phần tử và thuộc tính có id được đặt.
- bên trongHTML: Để truy cập nội dung của một phần tử.
Hãy thử ví dụ này xem sao:
<html> <head> <title>DOM!!!</title> </head> <body> <h1 id="one">Welcome</h1> <p>This is the welcome message.</p> <h2>Technology</h2> <p>This is the technology section.</p> <script type="text/javascript"> var text = document.getElementById("one").innerHTML; alert("The first heading is " + text); </script> </body> </html>
Hộp thoại cảnh báo xác nhận rằng getElementById đã tìm thấy tiêu đề và innerHTML đã trả về văn bản được lưu trữ bên trong tiêu đề đó.
Đọc từng đoạn văn bằng getElementsByTagName
getElementsByTagName: Để truy cập các phần tử và thuộc tính bằng tên thẻ. Phương thức này sẽ trả về một mảng của tất cả các mục có cùng tên thẻ.
Hãy thử ví dụ này xem sao:
<html> <head> <title>DOM!!!</title> </head> <body> <h1>Welcome</h1> <p>This is the welcome message.</p> <h2>Technology</h2> <p id="second">This is the technology section.</p> <script type="text/javascript"> var paragraphs = document.getElementsByTagName("p"); alert("Content in the second paragraph is " + paragraphs[1].innerHTML); document.getElementById("second").innerHTML = "The orginal message is changed."; </script> </body> </html>
Vì getElementsByTagName trả về một tập hợp trực tiếp nên paragraphs[1] đề cập đến đoạn văn thứ hai trong tài liệu và việc cập nhật innerHTML sẽ ngay lập tức ghi đè lên văn bản của nó trên màn hình.
Tạo và xóa các phần tử bằng hàm createElement và removeChild.
Ngoài việc thay đổi những gì đã có trên trang, DOM cho phép bạn thêm các phần tử hoàn toàn mới hoặc xóa các phần tử hiện có:
- createElement(): Tạo một nút phần tử mới trong bộ nhớ.
- appendChild(): Gắn một nút làm con cuối cùng của phần tử cha.
- setAttribute(): Thêm hoặc cập nhật một thuộc tính, chẳng hạn như
classorhref, trên một phần tử. - removeChild(): Xóa một nút con được chỉ định khỏi nút cha của nó.
Ví dụ dưới đây tạo một mục mới trong danh sách, gán văn bản và lớp cho mục đó, thêm mục này vào một danh sách hiện có, và sau đó xóa mục đầu tiên khỏi chính danh sách đó:
const list = document.getElementById("myList"); const newItem = document.createElement("li"); newItem.textContent = "Freshly added item"; newItem.setAttribute("class", "highlight"); list.appendChild(newItem); list.removeChild(list.firstElementChild);
Chỉ riêng phương thức `createElement()` không hiển thị bất cứ thứ gì, vì nút đó vẫn chỉ tồn tại trong bộ nhớ. Nó chỉ xuất hiện khi phương thức `appendChild()` hoặc một phương thức tương tự như `prepend()` gắn nó vào đâu đó bên trong cây hiển thị. Các trình duyệt hiện đại cũng hỗ trợ phương thức ngắn gọn hơn `node.remove()`, phương thức này xóa trực tiếp một phần tử mà không cần tham chiếu đến phần tử cha của nó, không giống như cú pháp cũ `parent.removeChild(node)`.
Cách xử lý sự kiện trong JavaScript
Sự kiện là bất kỳ hành động nào mà trình duyệt có thể phát hiện, chẳng hạn như nhấp chuột, nhấn phím hoặc tải trang. Bạn có thể thêm trình xử lý sự kiện vào một phần tử cụ thể theo hai cách chính.
Gắn trình xử lý bằng onclick hoặc addEventListener
Phương pháp đầu tiên, theo cách cũ hơn, gán trực tiếp một hàm cho thuộc tính on-event của một phần tử:
document.getElementById(id).onclick=function()
{
lines of code to be executed
}
HOẶC, sử dụng phương pháp addEventListener() hiện đại và linh hoạt hơn:
document.getElementById(id).addEventListener("click", functionname)
Phương thức `addEventListener()` thường được ưu tiên sử dụng vì nó cho phép bạn gắn nhiều trình xử lý vào cùng một sự kiện trên cùng một phần tử, và nó chấp nhận một đối số thứ ba tùy chọn để kiểm soát việc bắt sự kiện, sẽ được đề cập sau trong phần này. Nó cũng được kết hợp với `removeEventListener()`, phương thức này sẽ gỡ bỏ trình xử lý khi không còn cần thiết nữa, điều mà thuộc tính `onclick` không thể tự thực hiện.
HTML cũng hỗ trợ kiểu thứ ba: trình xử lý nội tuyến được viết trực tiếp trên thẻ, chẳng hạn như <button onclick="clicked()">Click Me</button>Các trình xử lý nội tuyến trộn lẫn mã đánh dấu với logic và nhanh chóng trở nên khó bảo trì, vì vậy hầu hết chúng đều không được sử dụng. JavaCác nhà phát triển kịch bản chỉ sử dụng chúng cho các bản demo nhanh và dựa vào addEventListener() cho các ứng dụng thực tế.
Hãy thử: Một ví dụ hoàn chỉnh về sự kiện nhấp chuột
Hãy thử ví dụ này xem sao:
<html> <head> <title>DOM!!!</title> </head> <body> <input type="button" id="btnClick" value="Click Me!!" /> <script type="text/javascript"> document.getElementById("btnClick").addEventListener("click", clicked); function clicked() { alert("You clicked me!!!"); } </script> </body> </html>
Việc nhấp vào nút sẽ kích hoạt hàm clicked(), hàm này sẽ gây ra một sự kiện. JavaHộp thoại cảnh báo của tập lệnh xác nhận rằng trình xử lý sự kiện đã chạy thành công.
Đối tượng Sự kiện
Mỗi trình xử lý sự kiện tự động nhận một đối tượng sự kiện làm đối số đầu tiên. Đối tượng này chứa các thông tin hữu ích về những gì đã xảy ra, bao gồm event.target (phần tử chính xác mà hành động bắt nguồn), event.type (tên sự kiện, chẳng hạn như “click”) và các phương thức như event.preventDefault(), phương thức này ngăn chặn hành vi mặc định của trình duyệt, chẳng hạn như theo một liên kết hoặc gửi một biểu mẫu.
document.getElementById("btnClick").addEventListener("click", function(event) { console.log("Clicked element: " + event.target.id); });
Hai thuộc tính nữa hoàn thiện đối tượng sự kiện: event.currentTarget Luôn tham chiếu đến phần tử mà trình lắng nghe được gắn vào, ngay cả khi event.target báo cáo một phần tử con lồng nhau, và event.stopPropagation() dừng một sự kiện trước khi nó tiếp tục lan truyền hoặc bắt giữ thêm bất kỳ điều gì. Cùng với preventDefault(), các công cụ này cung cấp cho trình xử lý quyền kiểm soát chính xác đối với những gì sẽ xảy ra tiếp theo.
Sự kiện BubblThu thập, nắm bắt và ủy quyền
Khi một sự kiện được kích hoạt trên một phần tử lồng nhau, nó không dừng lại ở đó. Trong trường hợp này, sủi bọt Trong giai đoạn này, sự kiện di chuyển từ phần tử mục tiêu lên trên, thông qua từng phần tử tổ tiên, cho đến tận tài liệu. Trong capturing Trong giai đoạn này, giai đoạn diễn ra đầu tiên và là tùy chọn, sự kiện thay vì lan truyền từ tài liệu xuống mục tiêu trước khi quá trình lan truyền bắt đầu. Vượt qua {capture: true} là đối số thứ ba cho hàm addEventListener() để lắng nghe trong giai đoạn bắt sự kiện.
Đoàn sự kiện Phương pháp này tận dụng cơ chế lan truyền sự kiện: thay vì gắn một trình lắng nghe riêng biệt cho mỗi phần tử con, bạn chỉ cần gắn một trình lắng nghe cho một phần tử cha chung và kiểm tra `event.target` để xác định phần tử con nào đã kích hoạt nó. Điều này giúp tiết kiệm bộ nhớ và tự động bao phủ các phần tử được thêm vào trang sau này.
const list = document.getElementById("myList"); list.addEventListener("click", function(event) { if (event.target.tagName === "LI") { alert("You clicked " + event.target.textContent); } });
Ủy quyền, cùng với cơ chế lan truyền và bắt giữ, cho phép bạn kiểm soát chi tiết cách DOM và các sự kiện hoạt động. JavaĐoạn mã sẽ tự động phản hồi khi trang web trở nên tương tác hơn.

