Giới thiệu
Khi bạn nhấp vào một phần tử bên trong các phần tử lồng nhau, sự kiện không chỉ xảy ra trên phần tử đó — nó sẽ di chuyển qua DOM. Có hai cách mà điều này có thể xảy ra: capturing và bubbling. Hiểu rõ hai khái niệm này sẽ giúp bạn quản lý sự kiện hiệu quả hơn trong các ứng dụng web.
Mục lục
- Event Capturing
- Event Bubbling
- Mặc định trong JavaScript
- Thứ tự dòng sự kiện
- Tại sao điều này quan trọng?
- Mô hình tư duy nhanh
- Thực hành và Ví dụ
- Câu hỏi thường gặp
Event Capturing (trickle down)
- Sự kiện bắt đầu từ đầu (
document) và đi xuống qua từng phần tử cha cho đến khi đến được mục tiêu. - Phân tích: ông bà gửi một tin nhắn → cha mẹ → con cái.
Ví dụ về Event Capturing
javascript
// Capturing
div.addEventListener(
"click",
() => {
console.log("DIV clicked during capturing!");
},
true // 👈 kích hoạt capturing
);
Event Bubbling (bubble up)
- Sự kiện bắt đầu từ phần tử mục tiêu và sau đó đi lên qua các phần tử cha cho đến gốc (
document). - Phân tích: bọt khí nổi lên từ đáy cốc đến đỉnh cốc.
Ví dụ về Event Bubbling
javascript
// Bubbling (mặc định)
button.addEventListener("click", () => {
console.log("Button clicked!");
});
Mặc định trong JavaScript
- Theo mặc định, JavaScript sử dụng bubbling.
- Để sử dụng capturing, bạn cần truyền
truelàm tham số thứ ba trongaddEventListener.
Thứ tự dòng sự kiện
Khi bạn nhấp vào nút:
- Giai đoạn capturing: document → body → div → button
- Giai đoạn mục tiêu: chính nút đó
- Giai đoạn bubbling: button → div → body → document
Tại sao điều này quan trọng?
- Capturing: ít phổ biến hơn, hữu ích nếu bạn muốn chặn sự kiện sớm.
- Bubbling: rất phổ biến, tuyệt vời cho event delegation (gán một listener cho một phần tử cha thay vì mỗi phần tử con).
Best Practices
- Sử dụng event delegation để giảm số lượng listeners.
- Tránh sử dụng cả hai phương thức trong cùng một ứng dụng nếu không cần thiết.
Common Pitfalls
- Không hiểu rõ thứ tự của các giai đoạn sự kiện có thể dẫn đến các lỗi khó chẩn đoán.
- Quên rằng capturing cần tham số
true.
Performance Tips
- Event delegation giúp tiết kiệm tài nguyên khi bạn có nhiều phần tử con.
- Kiểm tra hiệu suất để đảm bảo rằng không có quá nhiều sự kiện được xử lý cùng một lúc.
Mô hình tư duy nhanh
- Capturing = trickle down (phần tử cha → phần tử con)
- Bubbling = bubble up (phần tử con → phần tử cha)
Thực hành và Ví dụ
Hãy thử thực hành với một ứng dụng nhỏ để hiểu rõ hơn về capturing và bubbling. Dưới đây là một ví dụ đơn giản:
html
<div id="parent">
<button id="child">Click Me!</button>
</div>
<script>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener('click', () => {
console.log('Parent clicked!');
});
child.addEventListener('click', () => {
console.log('Child clicked!');
});
</script>
Khi bạn nhấp vào nút, bạn sẽ thấy thông điệp từ cả hai listener. Bây giờ hãy thử thêm true vào listener của phần tử cha để thấy sự khác biệt.
Câu hỏi thường gặp
1. Event Bubbling và Capturing khác nhau như thế nào?
Event Bubbling là khi sự kiện đi lên từ phần tử mục tiêu, trong khi Event Capturing là khi sự kiện đi xuống từ phần tử gốc.
2. Có thể sử dụng cả hai phương thức cùng một lúc không?
Có thể, nhưng điều này có thể gây nhầm lẫn và thường không được khuyến khích.
3. Khi nào nên sử dụng Capturing?
Nên sử dụng Capturing khi bạn muốn chặn một sự kiện trước khi nó đến được phần tử mục tiêu.
Kết luận
Bây giờ bạn đã biết cách sự kiện di chuyển trong JavaScript! Hãy thực hành với các ứng dụng của riêng bạn và áp dụng những kiến thức này vào các dự án thực tế. Đừng quên theo dõi blog của chúng tôi để cập nhật thêm nhiều kiến thức hữu ích khác về JavaScript và phát triển web!